From 187f44a2b14ba0982cbde8c2e765a8aceb2ac836 Mon Sep 17 00:00:00 2001 From: Christy Karpinski Date: Tue, 6 Jun 2023 17:11:39 -0500 Subject: [PATCH 1/4] adjusted title tag for work show page, a bit more css, changed generic to general on the modal where you choose work type --- app/assets/stylesheets/application.css | 1 + app/assets/stylesheets/atla-overrides.scss | 33 ++ app/presenters/hyrax/file_set_presenter.rb | 128 ++++++++ app/presenters/hyrax/work_show_presenter.rb | 333 ++++++++++++++++++++ config/environments/development.rb | 2 +- config/locales/generic_work.de.yml | 2 +- config/locales/generic_work.en.yml | 2 +- config/locales/generic_work.es.yml | 2 +- config/locales/generic_work.fr.yml | 2 +- config/locales/generic_work.it.yml | 2 +- config/locales/generic_work.pt-.yml | 2 +- config/locales/generic_work.pt-BR.yml | 2 +- 12 files changed, 503 insertions(+), 8 deletions(-) create mode 100644 app/assets/stylesheets/atla-overrides.scss create mode 100644 app/presenters/hyrax/file_set_presenter.rb create mode 100644 app/presenters/hyrax/work_show_presenter.rb diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index c90e7eba..77605f43 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -18,4 +18,5 @@ *= require dataTables/bootstrap/3/jquery.dataTables.bootstrap *= require bootstrap-datepicker *= require_self + *= require atla-overrides */ diff --git a/app/assets/stylesheets/atla-overrides.scss b/app/assets/stylesheets/atla-overrides.scss new file mode 100644 index 00000000..94c8f76f --- /dev/null +++ b/app/assets/stylesheets/atla-overrides.scss @@ -0,0 +1,33 @@ +html, body { + font-family: 'Muli', Helvetica, sans-serif; + font-size:1em; +} + +img {max-width:100%;} + + +/* Work show metadata layout */ +.works-show p.work_description {margin-top:1em;} +.works-show dl.work-show {margin-top: 1em;} +.work-show ul.tabular, .scholarly_show .work-show ul.tabular{padding-inline-start: 0px;} +.work-show dt {padding-bottom:0;} + +/* hide work type on work show pages */ +.works-show .work-type-tag {display:none;} + +/* Collection show layout */ +.hyc-banner .hyc-title h1, .hyc-banner .hyc-bugs div{ + color:rgb(51, 51, 51); + text-shadow:none; +} + +.hyc-banner .hyc-title .label { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; +} + +.hyc-banner {min-height:95px;} + +/* admin dashboard available works ETD all caps*/ +.dashboard label[for="input-Etd"] {text-transform: uppercase;} diff --git a/app/presenters/hyrax/file_set_presenter.rb b/app/presenters/hyrax/file_set_presenter.rb new file mode 100644 index 00000000..f035cd93 --- /dev/null +++ b/app/presenters/hyrax/file_set_presenter.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true +module Hyrax + class FileSetPresenter + include ModelProxy + include PresentsAttributes + include CharacterizationBehavior + include WithEvents + include DisplaysImage + + attr_accessor :solr_document, :current_ability, :request + + # @param [SolrDocument] solr_document + # @param [Ability] current_ability + # @param [ActionDispatch::Request] request the http request context + def initialize(solr_document, current_ability, request = nil) + @solr_document = solr_document + @current_ability = current_ability + @request = request + end + + # CurationConcern methods + delegate :stringify_keys, :human_readable_type, :collection?, :image?, :video?, + :audio?, :pdf?, :office_document?, :representative_id, :to_s, to: :solr_document + + # Methods used by blacklight helpers + delegate :has?, :first, :fetch, to: :solr_document + + # Metadata Methods + delegate :title, :label, :description, :creator, :contributor, :subject, + :publisher, :language, :date_uploaded, + :embargo_release_date, :lease_expiration_date, + :depositor, :keyword, :title_or_label, :keyword, + :date_created, :date_modified, :itemtype, + :original_file_id, + to: :solr_document + + delegate :member_of_collection_ids, to: :parent + + def workflow + nil + end + + def single_use_links + @single_use_links ||= SingleUseLink.where(item_id: id).map { |link| link_presenter_class.new(link) } + end + + # The title of the webpage that shows this FileSet. + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + + # The first title assertion + def first_title + title.first + end + + # The link text when linking to the show page of this FileSet + def link_name + current_ability.can?(:read, id) ? first_title : 'File' + end + + ## + # @deprecated use `::Ability.can?(:edit, presenter)`. Hyrax views calling + # presenter {#editor} methods will continue to call them until Hyrax + # 4.0.0. The deprecation time horizon for the presenter methods themselves + # is 5.0.0. + def editor? + current_ability.can?(:edit, self) + end + + def tweeter + TwitterPresenter.twitter_handle_for(user_key: depositor) + end + + def license + return if solr_document.license.nil? + solr_document.license.first + end + + def stats_path + Hyrax::Engine.routes.url_helpers.stats_file_path(self, locale: I18n.locale) + end + + def events(size = 100) + super(size) + end + + # This overrides the method in WithEvents + def event_class + solr_document.to_model.model_name.name + end + + def fixity_check_status + Hyrax::FixityStatusPresenter.new(id).render_file_set_status + end + + ## + # @return [WorkShowPresenter, nil] +nil+ if no parent can be found + def parent + @parent_presenter ||= fetch_parent_presenter + end + + def user_can_perform_any_action? + Deprecation.warn("We're removing Hyrax::FileSetPresenter.user_can_perform_any_action? in Hyrax 4.0.0; Instead use can? in view contexts.") + current_ability.can?(:edit, id) || current_ability.can?(:destroy, id) || current_ability.can?(:download, id) + end + + private + + def link_presenter_class + SingleUseLinkPresenter + end + + def fetch_parent_presenter + ids = Hyrax::SolrService.query("{!field f=member_ids_ssim}#{id}", fl: Hyrax.config.id_field) + .map { |x| x.fetch(Hyrax.config.id_field) } + Hyrax.logger.warn("Couldn't find a parent work for FileSet: #{id}.") if ids.empty? + ids.each do |id| + doc = ::SolrDocument.find(id) + next if current_ability.can?(:edit, doc) + raise WorkflowAuthorizationException if doc.suppressed? && current_ability.can?(:read, doc) + end + Hyrax::PresenterFactory.build_for(ids: ids, + presenter_class: WorkShowPresenter, + presenter_args: current_ability).first + end + end +end diff --git a/app/presenters/hyrax/work_show_presenter.rb b/app/presenters/hyrax/work_show_presenter.rb new file mode 100644 index 00000000..a224c85a --- /dev/null +++ b/app/presenters/hyrax/work_show_presenter.rb @@ -0,0 +1,333 @@ +# frozen_string_literal: true +module Hyrax + class WorkShowPresenter + include ModelProxy + include PresentsAttributes + + ## + # @!attribute [w] member_presenter_factory + # @return [MemberPresenterFactory] + attr_writer :member_presenter_factory + attr_accessor :solr_document, :current_ability, :request + + class_attribute :collection_presenter_class, :presenter_factory_class + + # modify this attribute to use an alternate presenter class for the collections + self.collection_presenter_class = CollectionPresenter + self.presenter_factory_class = MemberPresenterFactory + + # Methods used by blacklight helpers + delegate :has?, :first, :fetch, :export_formats, :export_as, to: :solr_document + + # delegate fields from Hyrax::Works::Metadata to solr_document + delegate :based_near_label, :related_url, :depositor, :identifier, :resource_type, + :keyword, :itemtype, :admin_set, :rights_notes, :access_right, :abstract, to: :solr_document + + # @param [SolrDocument] solr_document + # @param [Ability] current_ability + # @param [ActionDispatch::Request] request the http request context. Used so + # the GraphExporter knows what URLs to draw. + def initialize(solr_document, current_ability, request = nil) + @solr_document = Hyrax::SolrDocument::OrderedMembers.decorate(solr_document) + @current_ability = current_ability + @request = request + end + + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + + # CurationConcern methods + delegate :stringify_keys, :human_readable_type, :collection?, :to_s, :suppressed?, + to: :solr_document + + # Metadata Methods + delegate :title, :date_created, :description, + :creator, :contributor, :subject, :publisher, :language, :embargo_release_date, + :lease_expiration_date, :license, :source, :rights_statement, :thumbnail_id, :representative_id, + :rendering_ids, :member_of_collection_ids, :alternative_title, :bibliographic_citation, to: :solr_document + + def workflow + @workflow ||= WorkflowPresenter.new(solr_document, current_ability) + end + + def inspect_work + @inspect_workflow ||= InspectWorkPresenter.new(solr_document, current_ability) + end + + # @return [String] a download URL, if work has representative media, or a blank string + def download_url + return '' if representative_presenter.nil? + Hyrax::Engine.routes.url_helpers.download_url(representative_presenter, host: request.host) + end + + # @return [Boolean] render a IIIF viewer + def iiif_viewer? + representative_id.present? && + representative_presenter.present? && + representative_presenter.image? && + Hyrax.config.iiif_image_server? && + members_include_viewable_image? + end + + alias universal_viewer? iiif_viewer? + deprecation_deprecate universal_viewer?: "use iiif_viewer? instead" + + # @return [Symbol] the name of the IIIF viewer partial to render + # @example A work presenter with a custom iiif viewer + # module Hyrax + # class GenericWorkPresenter < Hyrax::WorkShowPresenter + # def iiif_viewer + # :my_iiif_viewer + # end + # end + # end + # + # Custom iiif viewer partial at app/views/hyrax/base/iiif_viewers/_my_iiif_viewer.html.erb + #

My IIIF Viewer!

+ # >Manifest + def iiif_viewer + :universal_viewer + end + + # @return FileSetPresenter presenter for the representative FileSets + def representative_presenter + return nil if representative_id.blank? + @representative_presenter ||= + begin + result = member_presenters([representative_id]).first + return nil if result.try(:id) == id + result.try(:representative_presenter) || result + rescue Hyrax::ObjectNotFoundError + Hyrax.logger.warn "Unable to find representative_id #{representative_id} for work #{id}" + return nil + end + end + + # Get presenters for the collections this work is a member of via the member_of_collections association. + # @return [Array] presenters + def member_of_collection_presenters + PresenterFactory.build_for(ids: member_of_authorized_parent_collections, + presenter_class: collection_presenter_class, + presenter_args: presenter_factory_arguments) + end + + def date_modified + solr_document.date_modified.try(:to_formatted_s, :standard) + end + + def date_uploaded + solr_document.date_uploaded.try(:to_formatted_s, :standard) + end + + def link_name + current_ability.can?(:read, id) ? to_s : 'Private' + end + + def export_as_nt + graph.dump(:ntriples) + end + + def export_as_jsonld + graph.dump(:jsonld, standard_prefixes: true) + end + + def export_as_ttl + graph.dump(:ttl) + end + + ## + # @deprecated use `::Ability.can?(:edit, presenter)`. Hyrax views calling + # presenter {#editor} methods will continue to call them until Hyrax + # 4.0.0. The deprecation time horizon for the presenter methods themselves + # is 5.0.0. + def editor? + current_ability.can?(:edit, self) + end + + def tweeter + TwitterPresenter.twitter_handle_for(user_key: depositor) + end + + def presenter_types + Hyrax.config.registered_curation_concern_types.map(&:underscore) + ["collection"] + end + + # @return [Array] presenters grouped by model name, used to show the parents of this object + def grouped_presenters(filtered_by: nil, except: nil) + # TODO: we probably need to retain collection_presenters (as parent_presenters) + # and join this with member_of_collection_presenters + grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys(&:human) + grouped.select! { |obj| obj.casecmp(filtered_by).zero? } unless filtered_by.nil? + grouped.reject! { |obj| except.map(&:downcase).include? obj.downcase } unless except.nil? + grouped + end + + def work_featurable? + user_can_feature_works? && solr_document.public? + end + + def display_feature_link? + work_featurable? && FeaturedWork.can_create_another? && !featured? + end + + def display_unfeature_link? + work_featurable? && featured? + end + + def stats_path + Hyrax::Engine.routes.url_helpers.stats_work_path(self, locale: I18n.locale) + end + + def model + solr_document.to_model + end + + delegate :member_presenters, :ordered_ids, :file_set_presenters, :work_presenters, to: :member_presenter_factory + + # @return [Array] list to display with Kaminari pagination + def list_of_item_ids_to_display + paginated_item_list(page_array: authorized_item_ids) + end + + ## + # @deprecated use `#member_presenters(ids)` instead + # + # @param [Array] ids a list of ids to build presenters for + # @return [Array] presenters for the array of ids (not filtered by class) + def member_presenters_for(an_array_of_ids) + Deprecation.warn("Use `#member_presenters` instead.") + member_presenters(an_array_of_ids) + end + + # @return [Integer] total number of pages of viewable items + def total_pages + (total_items.to_f / rows_from_params.to_f).ceil + end + + def manifest_url + manifest_helper.polymorphic_url([:manifest, self]) + end + + # IIIF rendering linking property for inclusion in the manifest + # Called by the `iiif_manifest` gem to add a 'rendering' (eg. a link a download for the resource) + # + # @return [Array] array of rendering hashes + def sequence_rendering + solr_document.rendering_ids.each_with_object([]) do |file_set_id, renderings| + renderings << manifest_helper.build_rendering(file_set_id) + end.flatten + end + + # IIIF metadata for inclusion in the manifest + # Called by the `iiif_manifest` gem to add metadata + # + # @return [Array] array of metadata hashes + def manifest_metadata + Hyrax.config.iiif_metadata_fields.each_with_object([]) do |field, metadata| + metadata << { + 'label' => I18n.t("simple_form.labels.defaults.#{field}"), + 'value' => Array.wrap(send(field).map { |f| Loofah.fragment(f.to_s).scrub!(:whitewash).to_s }) + } + end + end + + ## + # @return [Integer] + def member_count + @member_count ||= member_presenters.count + end + + ## + # Given a set of collections, which the caller asserts the current ability + # can deposit to, decide whether to display actions to add this work to a + # collection. + # + # By default, this returns `true` if any collections are passed in OR the + # current ability can create a collection. + # + # @param collections [Enumerable<::Collection>, nil] list of collections to + # which the current ability can deposit + # + # @return [Boolean] a flag indicating whether to display collection deposit + # options. + def show_deposit_for?(collections:) + collections.present? || + current_ability.can?(:create_any, Hyrax.config.collection_class) + end + + ## + # @return [Array] + def valid_child_concerns + Hyrax::ChildTypes.for(parent: solr_document.hydra_model).to_a + end + + private + + # list of item ids to display is based on ordered_ids + def authorized_item_ids(filter_unreadable: Flipflop.hide_private_items?) + @member_item_list_ids ||= + filter_unreadable ? ordered_ids.reject { |id| !current_ability.can?(:read, id) } : ordered_ids + end + + # Uses kaminari to paginate an array to avoid need for solr documents for items here + def paginated_item_list(page_array:) + Kaminari.paginate_array(page_array, total_count: page_array.size).page(current_page).per(rows_from_params) + end + + def total_items + authorized_item_ids.size + end + + def rows_from_params + request.params[:rows].nil? ? Hyrax.config.show_work_item_rows : request.params[:rows].to_i + end + + def current_page + page = request.params[:page].nil? ? 1 : request.params[:page].to_i + page > total_pages ? total_pages : page + end + + def manifest_helper + @manifest_helper ||= ManifestHelper.new(request.base_url) + end + + def featured? + # only look this up if it's not boolean; ||= won't work here + @featured = FeaturedWork.where(work_id: solr_document.id).exists? if @featured.nil? + @featured + end + + def user_can_feature_works? + current_ability.can?(:create, FeaturedWork) + end + + def presenter_factory_arguments + [current_ability, request] + end + + def member_presenter_factory + @member_presenter_factory ||= + if solr_document.hydra_model < Valkyrie::Resource + PcdmMemberPresenterFactory.new(solr_document, current_ability) + else + self.class + .presenter_factory_class + .new(solr_document, current_ability, request) + end + end + + def graph + GraphExporter.new(solr_document, hostname: request.host).fetch + end + + # @return [Array] member_of_collection_ids with current_ability access + def member_of_authorized_parent_collections + @member_of ||= Hyrax::CollectionMemberService.run(solr_document, current_ability).map(&:id) + end + + def members_include_viewable_image? + file_set_presenters.any? { |presenter| presenter.image? && current_ability.can?(:read, presenter.id) } + end + end +end diff --git a/config/environments/development.rb b/config/environments/development.rb index 9bafa102..f51b09c2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -40,7 +40,7 @@ # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. - # config.assets.debug = true + config.assets.debug = true # Suppress logger output for asset requests. config.assets.quiet = true diff --git a/config/locales/generic_work.de.yml b/config/locales/generic_work.de.yml index 567c170b..50d71cdb 100644 --- a/config/locales/generic_work.de.yml +++ b/config/locales/generic_work.de.yml @@ -6,4 +6,4 @@ de: select_type: generic_work: description: 'Arbeitstyp: Generische Arbeit. Wählen Sie diesen Typ für Ihre Arbeit, die Sie hinzufügen möchten, aus, wenn die unten aufgeführten, spezielleren Arbeitstypen nicht für Ihre Arbeit geeignet erscheinen.' - name: Generische Arbeit + name: Allgemeine Arbeit diff --git a/config/locales/generic_work.en.yml b/config/locales/generic_work.en.yml index a47e7e6e..54697566 100644 --- a/config/locales/generic_work.en.yml +++ b/config/locales/generic_work.en.yml @@ -6,4 +6,4 @@ en: select_type: generic_work: description: General purpose work type. Select this if the more specific work types below are not suited to the work you want to add. - name: Generic Work \ No newline at end of file + name: General Work diff --git a/config/locales/generic_work.es.yml b/config/locales/generic_work.es.yml index 5802304d..eed114f2 100644 --- a/config/locales/generic_work.es.yml +++ b/config/locales/generic_work.es.yml @@ -6,4 +6,4 @@ es: select_type: generic_work: description: Tipo de trabajo de propósito general. Seleccione esta opción si los tipos de trabajo más específicos de abajo no son adecuados para el trabajo que desea agregar. - name: Trabajo Genérico + name: Trabajo general diff --git a/config/locales/generic_work.fr.yml b/config/locales/generic_work.fr.yml index 9ccf1f93..89da2d1a 100644 --- a/config/locales/generic_work.fr.yml +++ b/config/locales/generic_work.fr.yml @@ -6,4 +6,4 @@ fr: select_type: generic_work: description: Type de travail à usage général. Sélectionnez cette option si les types de travaux plus spécifiques ci-dessous ne conviennent pas au travail que vous souhaitez ajouter. - name: Œuvres Génériques + name: Travail général diff --git a/config/locales/generic_work.it.yml b/config/locales/generic_work.it.yml index 4b3c604a..2d4aca03 100644 --- a/config/locales/generic_work.it.yml +++ b/config/locales/generic_work.it.yml @@ -6,4 +6,4 @@ it: select_type: generic_work: description: Tipo di opere di tipo generale. Selezionare questa opzione se i tipi di opere più specifici di seguito non sono adatti al opere che si desidera aggiungere. - name: Opere Generiche + name: Opere generale diff --git a/config/locales/generic_work.pt-.yml b/config/locales/generic_work.pt-.yml index 8db92363..3591964a 100644 --- a/config/locales/generic_work.pt-.yml +++ b/config/locales/generic_work.pt-.yml @@ -6,4 +6,4 @@ pt-: select_type: generic_work: description: Tipo de trabalho de uso geral. Selecione esta opção se os tipos de trabalho mais específicos abaixo não forem adequados para o trabalho que você deseja adicionar. - name: Trabalho Genérico + name: Trabalho geral diff --git a/config/locales/generic_work.pt-BR.yml b/config/locales/generic_work.pt-BR.yml index 09b4d3a0..8afcf17d 100644 --- a/config/locales/generic_work.pt-BR.yml +++ b/config/locales/generic_work.pt-BR.yml @@ -6,4 +6,4 @@ pt-BR: select_type: generic_work: description: Tipo de trabalho de propósito geral. Selecione isso se os tipos de trabalho mais específicos abaixo não forem adequados ao trabalho que deseja adicionar. - name: Trabalho Genérico + name: Trabalho geral From f0a9663e8288e51c09561ff5c67fd7d4b472b9ea Mon Sep 17 00:00:00 2001 From: Christy Karpinski Date: Thu, 6 Jul 2023 11:40:23 -0500 Subject: [PATCH 2/4] using decorator file to override title tag for pages --- app/presenters/hyrax/file_set_presenter.rb | 128 ------------------ .../hyrax/file_set_presenter_decorator.rb | 13 ++ 2 files changed, 13 insertions(+), 128 deletions(-) delete mode 100644 app/presenters/hyrax/file_set_presenter.rb create mode 100644 app/presenters/hyrax/file_set_presenter_decorator.rb diff --git a/app/presenters/hyrax/file_set_presenter.rb b/app/presenters/hyrax/file_set_presenter.rb deleted file mode 100644 index f035cd93..00000000 --- a/app/presenters/hyrax/file_set_presenter.rb +++ /dev/null @@ -1,128 +0,0 @@ -# frozen_string_literal: true -module Hyrax - class FileSetPresenter - include ModelProxy - include PresentsAttributes - include CharacterizationBehavior - include WithEvents - include DisplaysImage - - attr_accessor :solr_document, :current_ability, :request - - # @param [SolrDocument] solr_document - # @param [Ability] current_ability - # @param [ActionDispatch::Request] request the http request context - def initialize(solr_document, current_ability, request = nil) - @solr_document = solr_document - @current_ability = current_ability - @request = request - end - - # CurationConcern methods - delegate :stringify_keys, :human_readable_type, :collection?, :image?, :video?, - :audio?, :pdf?, :office_document?, :representative_id, :to_s, to: :solr_document - - # Methods used by blacklight helpers - delegate :has?, :first, :fetch, to: :solr_document - - # Metadata Methods - delegate :title, :label, :description, :creator, :contributor, :subject, - :publisher, :language, :date_uploaded, - :embargo_release_date, :lease_expiration_date, - :depositor, :keyword, :title_or_label, :keyword, - :date_created, :date_modified, :itemtype, - :original_file_id, - to: :solr_document - - delegate :member_of_collection_ids, to: :parent - - def workflow - nil - end - - def single_use_links - @single_use_links ||= SingleUseLink.where(item_id: id).map { |link| link_presenter_class.new(link) } - end - - # The title of the webpage that shows this FileSet. - def page_title - "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" - end - - # The first title assertion - def first_title - title.first - end - - # The link text when linking to the show page of this FileSet - def link_name - current_ability.can?(:read, id) ? first_title : 'File' - end - - ## - # @deprecated use `::Ability.can?(:edit, presenter)`. Hyrax views calling - # presenter {#editor} methods will continue to call them until Hyrax - # 4.0.0. The deprecation time horizon for the presenter methods themselves - # is 5.0.0. - def editor? - current_ability.can?(:edit, self) - end - - def tweeter - TwitterPresenter.twitter_handle_for(user_key: depositor) - end - - def license - return if solr_document.license.nil? - solr_document.license.first - end - - def stats_path - Hyrax::Engine.routes.url_helpers.stats_file_path(self, locale: I18n.locale) - end - - def events(size = 100) - super(size) - end - - # This overrides the method in WithEvents - def event_class - solr_document.to_model.model_name.name - end - - def fixity_check_status - Hyrax::FixityStatusPresenter.new(id).render_file_set_status - end - - ## - # @return [WorkShowPresenter, nil] +nil+ if no parent can be found - def parent - @parent_presenter ||= fetch_parent_presenter - end - - def user_can_perform_any_action? - Deprecation.warn("We're removing Hyrax::FileSetPresenter.user_can_perform_any_action? in Hyrax 4.0.0; Instead use can? in view contexts.") - current_ability.can?(:edit, id) || current_ability.can?(:destroy, id) || current_ability.can?(:download, id) - end - - private - - def link_presenter_class - SingleUseLinkPresenter - end - - def fetch_parent_presenter - ids = Hyrax::SolrService.query("{!field f=member_ids_ssim}#{id}", fl: Hyrax.config.id_field) - .map { |x| x.fetch(Hyrax.config.id_field) } - Hyrax.logger.warn("Couldn't find a parent work for FileSet: #{id}.") if ids.empty? - ids.each do |id| - doc = ::SolrDocument.find(id) - next if current_ability.can?(:edit, doc) - raise WorkflowAuthorizationException if doc.suppressed? && current_ability.can?(:read, doc) - end - Hyrax::PresenterFactory.build_for(ids: ids, - presenter_class: WorkShowPresenter, - presenter_args: current_ability).first - end - end -end diff --git a/app/presenters/hyrax/file_set_presenter_decorator.rb b/app/presenters/hyrax/file_set_presenter_decorator.rb new file mode 100644 index 00000000..48dcf314 --- /dev/null +++ b/app/presenters/hyrax/file_set_presenter_decorator.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# OVERRIDE Hyrax v3.5.0 to change what appears in the title tags for pages + +module Hyrax + module FileSetPresenterDecorator + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + end +end + +Hyrax::FileSetPresenter.prepend(Hyrax::FileSetPresenterDecorator) From 0f3923bfda5d2779a88ce7eb70943ed7f12284ba Mon Sep 17 00:00:00 2001 From: Christy Karpinski Date: Thu, 6 Jul 2023 17:12:26 -0500 Subject: [PATCH 3/4] using decorator file to override title tag for work show pages --- app/presenters/hyrax/work_show_presenter.rb | 333 ------------------ .../hyrax/work_show_presenter_decorator.rb | 12 + 2 files changed, 12 insertions(+), 333 deletions(-) delete mode 100644 app/presenters/hyrax/work_show_presenter.rb create mode 100644 app/presenters/hyrax/work_show_presenter_decorator.rb diff --git a/app/presenters/hyrax/work_show_presenter.rb b/app/presenters/hyrax/work_show_presenter.rb deleted file mode 100644 index a224c85a..00000000 --- a/app/presenters/hyrax/work_show_presenter.rb +++ /dev/null @@ -1,333 +0,0 @@ -# frozen_string_literal: true -module Hyrax - class WorkShowPresenter - include ModelProxy - include PresentsAttributes - - ## - # @!attribute [w] member_presenter_factory - # @return [MemberPresenterFactory] - attr_writer :member_presenter_factory - attr_accessor :solr_document, :current_ability, :request - - class_attribute :collection_presenter_class, :presenter_factory_class - - # modify this attribute to use an alternate presenter class for the collections - self.collection_presenter_class = CollectionPresenter - self.presenter_factory_class = MemberPresenterFactory - - # Methods used by blacklight helpers - delegate :has?, :first, :fetch, :export_formats, :export_as, to: :solr_document - - # delegate fields from Hyrax::Works::Metadata to solr_document - delegate :based_near_label, :related_url, :depositor, :identifier, :resource_type, - :keyword, :itemtype, :admin_set, :rights_notes, :access_right, :abstract, to: :solr_document - - # @param [SolrDocument] solr_document - # @param [Ability] current_ability - # @param [ActionDispatch::Request] request the http request context. Used so - # the GraphExporter knows what URLs to draw. - def initialize(solr_document, current_ability, request = nil) - @solr_document = Hyrax::SolrDocument::OrderedMembers.decorate(solr_document) - @current_ability = current_ability - @request = request - end - - def page_title - "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" - end - - # CurationConcern methods - delegate :stringify_keys, :human_readable_type, :collection?, :to_s, :suppressed?, - to: :solr_document - - # Metadata Methods - delegate :title, :date_created, :description, - :creator, :contributor, :subject, :publisher, :language, :embargo_release_date, - :lease_expiration_date, :license, :source, :rights_statement, :thumbnail_id, :representative_id, - :rendering_ids, :member_of_collection_ids, :alternative_title, :bibliographic_citation, to: :solr_document - - def workflow - @workflow ||= WorkflowPresenter.new(solr_document, current_ability) - end - - def inspect_work - @inspect_workflow ||= InspectWorkPresenter.new(solr_document, current_ability) - end - - # @return [String] a download URL, if work has representative media, or a blank string - def download_url - return '' if representative_presenter.nil? - Hyrax::Engine.routes.url_helpers.download_url(representative_presenter, host: request.host) - end - - # @return [Boolean] render a IIIF viewer - def iiif_viewer? - representative_id.present? && - representative_presenter.present? && - representative_presenter.image? && - Hyrax.config.iiif_image_server? && - members_include_viewable_image? - end - - alias universal_viewer? iiif_viewer? - deprecation_deprecate universal_viewer?: "use iiif_viewer? instead" - - # @return [Symbol] the name of the IIIF viewer partial to render - # @example A work presenter with a custom iiif viewer - # module Hyrax - # class GenericWorkPresenter < Hyrax::WorkShowPresenter - # def iiif_viewer - # :my_iiif_viewer - # end - # end - # end - # - # Custom iiif viewer partial at app/views/hyrax/base/iiif_viewers/_my_iiif_viewer.html.erb - #

My IIIF Viewer!

- # >Manifest - def iiif_viewer - :universal_viewer - end - - # @return FileSetPresenter presenter for the representative FileSets - def representative_presenter - return nil if representative_id.blank? - @representative_presenter ||= - begin - result = member_presenters([representative_id]).first - return nil if result.try(:id) == id - result.try(:representative_presenter) || result - rescue Hyrax::ObjectNotFoundError - Hyrax.logger.warn "Unable to find representative_id #{representative_id} for work #{id}" - return nil - end - end - - # Get presenters for the collections this work is a member of via the member_of_collections association. - # @return [Array] presenters - def member_of_collection_presenters - PresenterFactory.build_for(ids: member_of_authorized_parent_collections, - presenter_class: collection_presenter_class, - presenter_args: presenter_factory_arguments) - end - - def date_modified - solr_document.date_modified.try(:to_formatted_s, :standard) - end - - def date_uploaded - solr_document.date_uploaded.try(:to_formatted_s, :standard) - end - - def link_name - current_ability.can?(:read, id) ? to_s : 'Private' - end - - def export_as_nt - graph.dump(:ntriples) - end - - def export_as_jsonld - graph.dump(:jsonld, standard_prefixes: true) - end - - def export_as_ttl - graph.dump(:ttl) - end - - ## - # @deprecated use `::Ability.can?(:edit, presenter)`. Hyrax views calling - # presenter {#editor} methods will continue to call them until Hyrax - # 4.0.0. The deprecation time horizon for the presenter methods themselves - # is 5.0.0. - def editor? - current_ability.can?(:edit, self) - end - - def tweeter - TwitterPresenter.twitter_handle_for(user_key: depositor) - end - - def presenter_types - Hyrax.config.registered_curation_concern_types.map(&:underscore) + ["collection"] - end - - # @return [Array] presenters grouped by model name, used to show the parents of this object - def grouped_presenters(filtered_by: nil, except: nil) - # TODO: we probably need to retain collection_presenters (as parent_presenters) - # and join this with member_of_collection_presenters - grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys(&:human) - grouped.select! { |obj| obj.casecmp(filtered_by).zero? } unless filtered_by.nil? - grouped.reject! { |obj| except.map(&:downcase).include? obj.downcase } unless except.nil? - grouped - end - - def work_featurable? - user_can_feature_works? && solr_document.public? - end - - def display_feature_link? - work_featurable? && FeaturedWork.can_create_another? && !featured? - end - - def display_unfeature_link? - work_featurable? && featured? - end - - def stats_path - Hyrax::Engine.routes.url_helpers.stats_work_path(self, locale: I18n.locale) - end - - def model - solr_document.to_model - end - - delegate :member_presenters, :ordered_ids, :file_set_presenters, :work_presenters, to: :member_presenter_factory - - # @return [Array] list to display with Kaminari pagination - def list_of_item_ids_to_display - paginated_item_list(page_array: authorized_item_ids) - end - - ## - # @deprecated use `#member_presenters(ids)` instead - # - # @param [Array] ids a list of ids to build presenters for - # @return [Array] presenters for the array of ids (not filtered by class) - def member_presenters_for(an_array_of_ids) - Deprecation.warn("Use `#member_presenters` instead.") - member_presenters(an_array_of_ids) - end - - # @return [Integer] total number of pages of viewable items - def total_pages - (total_items.to_f / rows_from_params.to_f).ceil - end - - def manifest_url - manifest_helper.polymorphic_url([:manifest, self]) - end - - # IIIF rendering linking property for inclusion in the manifest - # Called by the `iiif_manifest` gem to add a 'rendering' (eg. a link a download for the resource) - # - # @return [Array] array of rendering hashes - def sequence_rendering - solr_document.rendering_ids.each_with_object([]) do |file_set_id, renderings| - renderings << manifest_helper.build_rendering(file_set_id) - end.flatten - end - - # IIIF metadata for inclusion in the manifest - # Called by the `iiif_manifest` gem to add metadata - # - # @return [Array] array of metadata hashes - def manifest_metadata - Hyrax.config.iiif_metadata_fields.each_with_object([]) do |field, metadata| - metadata << { - 'label' => I18n.t("simple_form.labels.defaults.#{field}"), - 'value' => Array.wrap(send(field).map { |f| Loofah.fragment(f.to_s).scrub!(:whitewash).to_s }) - } - end - end - - ## - # @return [Integer] - def member_count - @member_count ||= member_presenters.count - end - - ## - # Given a set of collections, which the caller asserts the current ability - # can deposit to, decide whether to display actions to add this work to a - # collection. - # - # By default, this returns `true` if any collections are passed in OR the - # current ability can create a collection. - # - # @param collections [Enumerable<::Collection>, nil] list of collections to - # which the current ability can deposit - # - # @return [Boolean] a flag indicating whether to display collection deposit - # options. - def show_deposit_for?(collections:) - collections.present? || - current_ability.can?(:create_any, Hyrax.config.collection_class) - end - - ## - # @return [Array] - def valid_child_concerns - Hyrax::ChildTypes.for(parent: solr_document.hydra_model).to_a - end - - private - - # list of item ids to display is based on ordered_ids - def authorized_item_ids(filter_unreadable: Flipflop.hide_private_items?) - @member_item_list_ids ||= - filter_unreadable ? ordered_ids.reject { |id| !current_ability.can?(:read, id) } : ordered_ids - end - - # Uses kaminari to paginate an array to avoid need for solr documents for items here - def paginated_item_list(page_array:) - Kaminari.paginate_array(page_array, total_count: page_array.size).page(current_page).per(rows_from_params) - end - - def total_items - authorized_item_ids.size - end - - def rows_from_params - request.params[:rows].nil? ? Hyrax.config.show_work_item_rows : request.params[:rows].to_i - end - - def current_page - page = request.params[:page].nil? ? 1 : request.params[:page].to_i - page > total_pages ? total_pages : page - end - - def manifest_helper - @manifest_helper ||= ManifestHelper.new(request.base_url) - end - - def featured? - # only look this up if it's not boolean; ||= won't work here - @featured = FeaturedWork.where(work_id: solr_document.id).exists? if @featured.nil? - @featured - end - - def user_can_feature_works? - current_ability.can?(:create, FeaturedWork) - end - - def presenter_factory_arguments - [current_ability, request] - end - - def member_presenter_factory - @member_presenter_factory ||= - if solr_document.hydra_model < Valkyrie::Resource - PcdmMemberPresenterFactory.new(solr_document, current_ability) - else - self.class - .presenter_factory_class - .new(solr_document, current_ability, request) - end - end - - def graph - GraphExporter.new(solr_document, hostname: request.host).fetch - end - - # @return [Array] member_of_collection_ids with current_ability access - def member_of_authorized_parent_collections - @member_of ||= Hyrax::CollectionMemberService.run(solr_document, current_ability).map(&:id) - end - - def members_include_viewable_image? - file_set_presenters.any? { |presenter| presenter.image? && current_ability.can?(:read, presenter.id) } - end - end -end diff --git a/app/presenters/hyrax/work_show_presenter_decorator.rb b/app/presenters/hyrax/work_show_presenter_decorator.rb new file mode 100644 index 00000000..649b4c8b --- /dev/null +++ b/app/presenters/hyrax/work_show_presenter_decorator.rb @@ -0,0 +1,12 @@ + +# OVERRIDE Hyrax v3.5.0 to change what appears in the title tags for pages + +module Hyrax + module WorkShowPresenterDecorator + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + end +end + +Hyrax::WorkShowPresenter.prepend(Hyrax::WorkShowPresenterDecorator) From 7eb1b6aab38e27487d59673f5d903e5d3f5867b1 Mon Sep 17 00:00:00 2001 From: Christy Karpinski Date: Thu, 6 Jul 2023 17:30:36 -0500 Subject: [PATCH 4/4] ran rubocop and auto corrected errors --- app/presenters/hyrax/file_set_presenter_decorator.rb | 10 +++++----- .../hyrax/work_show_presenter_decorator.rb | 12 +++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/presenters/hyrax/file_set_presenter_decorator.rb b/app/presenters/hyrax/file_set_presenter_decorator.rb index 48dcf314..7ed02ba5 100644 --- a/app/presenters/hyrax/file_set_presenter_decorator.rb +++ b/app/presenters/hyrax/file_set_presenter_decorator.rb @@ -3,11 +3,11 @@ # OVERRIDE Hyrax v3.5.0 to change what appears in the title tags for pages module Hyrax - module FileSetPresenterDecorator - def page_title - "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" - end - end + module FileSetPresenterDecorator + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + end end Hyrax::FileSetPresenter.prepend(Hyrax::FileSetPresenterDecorator) diff --git a/app/presenters/hyrax/work_show_presenter_decorator.rb b/app/presenters/hyrax/work_show_presenter_decorator.rb index 649b4c8b..52aa8407 100644 --- a/app/presenters/hyrax/work_show_presenter_decorator.rb +++ b/app/presenters/hyrax/work_show_presenter_decorator.rb @@ -1,12 +1,14 @@ +# frozen_string_literal: true + # OVERRIDE Hyrax v3.5.0 to change what appears in the title tags for pages module Hyrax - module WorkShowPresenterDecorator - def page_title - "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" - end - end + module WorkShowPresenterDecorator + def page_title + "#{title.first} | #{I18n.t('hyrax.product_name')} | ID: #{id}" + end + end end Hyrax::WorkShowPresenter.prepend(Hyrax::WorkShowPresenterDecorator)