diff --git a/Gemfile b/Gemfile
index a8e9c98c..f2b1c6be 100644
--- a/Gemfile
+++ b/Gemfile
@@ -9,9 +9,6 @@ gem 'rails', '~> 5.2.8.1'
gem "sqlite3", "~> 1.3.0"
# Use pg as the production database for Active Record
gem 'pg'
-# Use sitemap
-# See https://github.com/viseztrance/rails-sitemap
-gem 'sitemap'
# Use Passenger as the app server
# Update this when we update the Passenger docker container base image version
gem 'passenger', '6.0.17', require: "phusion_passenger/rack_handler"
@@ -88,6 +85,8 @@ gem "ffi", "~> 1.15"
gem 'json-canonicalization', '0.3.1' # https://github.com/dryruby/json-canonicalization/issues/2
+gem 'schoolie', '0.1.3'
+
gem 'prawn'
# SAML
gem 'omniauth-saml', '2.1.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index cdfdb3fc..7da1e809 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -893,6 +893,8 @@ GEM
sassc (2.4.0)
ffi (~> 1.9)
scanf (1.0.0)
+ schoolie (0.1.3)
+ actionview (~> 5)
select2-rails (3.5.11)
shacl (0.1.1)
json-ld (~> 3.1, >= 3.1.7)
@@ -908,7 +910,7 @@ GEM
rdf-xsd (~> 3.1)
sparql (~> 3.1)
sxp (~> 1.1)
- sidekiq (6.5.9)
+ sidekiq (6.5.10)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
@@ -1076,6 +1078,7 @@ DEPENDENCIES
rsolr (>= 1.0, < 3)
rspec-rails
sass-rails (~> 5.0)
+ schoolie (= 0.1.3)
sidekiq (~> 6)
simplecov
sitemap
diff --git a/app/assets/stylesheets/scholarspace/base/_base.scss b/app/assets/stylesheets/scholarspace/base/_base.scss
index c14b4701..9a74f3f1 100644
--- a/app/assets/stylesheets/scholarspace/base/_base.scss
+++ b/app/assets/stylesheets/scholarspace/base/_base.scss
@@ -158,7 +158,7 @@ html {
&.btn-categories {
width: 100%;
margin: 0.2em 0;
- padding: 0.3rem 2rem;
+ padding: 0.3rem 1rem;
border: 2px solid $gw-white;
background-color: $gw-white;
color: $gw-dark-blue;
diff --git a/app/assets/stylesheets/scholarspace/components/_homepage.scss b/app/assets/stylesheets/scholarspace/components/_homepage.scss
index 617067a3..161298d1 100644
--- a/app/assets/stylesheets/scholarspace/components/_homepage.scss
+++ b/app/assets/stylesheets/scholarspace/components/_homepage.scss
@@ -191,7 +191,7 @@
margin: 0;
#categories-container, #categories-tooltip {
- padding: 0 0 0 0.5em
+ padding: 1em 0 0 0.5em;
}
}
}
@@ -201,18 +201,18 @@
height: 100%;
#recent_docs {
- height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
- align-items: center;
+ align-items: baseline;
+ padding-top: 0.5em;
.recent-work {
width: 12vw;
margin: 0.5em 0.5em;
display: flex;
align-items: baseline;
- height: 18.5vw;
+ min-height: 18.5vw;
.image-wrapper {
position: relative;
@@ -258,18 +258,49 @@
align-items: center;
justify-content: center;
background-color: $gw-light-blue;
-
- h3 {
- font-size: 1em;
- text-decoration: underline;
- &:hover {
- color: $gw-hover-buff;
+ .title-wrapper {
+ -webkit-box-orient: vertical;
+ display: -webkit-box;
+ -webkit-line-clamp: 4;
+ padding: 0 1em;
+ overflow: hidden;
+ max-width: 100%;
+ text-align: center;
+
+ h3 {
+ font-size: 1em;
+ text-decoration: underline;
+ --max-lines: 4;
+ --line-height: 1.2;
+ max-height: calc(var(--max-lines) * 1em * var(--line-height));
+ line-height: var(--line-height);
+ position: relative;
+
+ &:hover {
+ color: $gw-hover-buff;
+ }
}
}
}
}
+ .keyword-wrapper {
+ -webkit-box-orient: vertical;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ overflow: hidden;
+ max-width: 100%;
+
+ .recent-field {
+ --max-lines: 2;
+ --line-height: 1.4;
+ height: calc(var(--max-lines) * 1em * var(--line-height));
+ line-height: var(--line-height);
+ position: relative;
+ }
+ }
+
@media (max-width: 1300px) {
width: 14vw;
@@ -305,10 +336,14 @@
@media (max-width: $mobile-max) {
flex-direction: column;
+ width: 80%;
+ align-items: center;
.recent-work {
- width: 100%;
margin: 2em 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
.image-wrapper {
height: 90.5vw;
@@ -431,10 +466,6 @@
@media (max-width: 1280px) {
flex-direction: column;
- #featured-h2 {
- width: 100%;
- }
-
.home-collections {
margin-bottom: 1em;
}
@@ -449,8 +480,12 @@
@media (max-width: 1280px) {
padding: 1.5em 0;
+
+ #featured-h2 {
+ width: 100%;
+ }
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/jobs/sitemap_regenerate_job.rb b/app/jobs/sitemap_regenerate_job.rb
index d8dd29fa..d2b7e720 100644
--- a/app/jobs/sitemap_regenerate_job.rb
+++ b/app/jobs/sitemap_regenerate_job.rb
@@ -4,7 +4,6 @@
class SitemapRegenerateJob < ApplicationJob
def perform
- Rake::Task['sitemap:generate'].invoke
- Rake::Task['sitemap:ping'].invoke
+ Rake::Task['schoolie:sitemap'].invoke
end
end
diff --git a/app/models/gw_etd.rb b/app/models/gw_etd.rb
index ec550926..d2c72a78 100644
--- a/app/models/gw_etd.rb
+++ b/app/models/gw_etd.rb
@@ -5,7 +5,7 @@ class GwEtd < ActiveFedora::Base
# Change this to restrict which works can be added as a child.
# self.valid_child_concerns = []
self.indexer = GwEtdIndexer
-
+
validates :title, presence: { message: 'Your work must have a title.' }
property :gw_affiliation, predicate: ::RDF::URI.new('http://scholarspace.library.gwu.edu/ns#gwaffiliation') do |index|
diff --git a/app/models/gw_work.rb b/app/models/gw_work.rb
index 657d9c8c..2c85a7ca 100644
--- a/app/models/gw_work.rb
+++ b/app/models/gw_work.rb
@@ -17,4 +17,4 @@ class GwWork < ActiveFedora::Base
end
include ::Hyrax::BasicMetadata
-end
+end
\ No newline at end of file
diff --git a/app/presenters/hyrax/gw_etd_presenter.rb b/app/presenters/hyrax/gw_etd_presenter.rb
index c4a4887b..f331a460 100644
--- a/app/presenters/hyrax/gw_etd_presenter.rb
+++ b/app/presenters/hyrax/gw_etd_presenter.rb
@@ -6,5 +6,11 @@ class GwEtdPresenter < GwWorkPresenter
def permanent_url
Scholarspace::Application.config.permanent_url_base + "etd/#{id}"
end
+
+ # scholarly? is used to determine whether or not
+ # the Google Scholar meta tags are rendered
+ def scholarly?
+ true
+ end
end
end
diff --git a/app/presenters/hyrax/gw_work_presenter.rb b/app/presenters/hyrax/gw_work_presenter.rb
index 2c705e78..db4efb98 100644
--- a/app/presenters/hyrax/gw_work_presenter.rb
+++ b/app/presenters/hyrax/gw_work_presenter.rb
@@ -5,5 +5,9 @@ class GwWorkPresenter < Hyrax::WorkShowPresenter
def permanent_url
Scholarspace::Application.config.permanent_url_base + "work/#{id}"
end
+
+ def scholarly?
+ false
+ end
end
end
diff --git a/app/views/hyrax/homepage/_recent_document.html.erb b/app/views/hyrax/homepage/_recent_document.html.erb
index a3cff852..24dae681 100644
--- a/app/views/hyrax/homepage/_recent_document.html.erb
+++ b/app/views/hyrax/homepage/_recent_document.html.erb
@@ -7,14 +7,18 @@
<%= render_thumbnail_tag(recent_document, {alt: "#{recent_document} #{ t('hyrax.homepage.admin_sets.thumbnail')}" }, {suppress_link: true}) %>
-
- <%= recent_document %>
-
+
+
+ <%= recent_document %>
+
+
<% end %>
-
- <%= t('hyrax.homepage.recently_uploaded.document.keyword_label') %>: <%= link_to_facet_list(recent_document.keyword, 'keyword', t('hyrax.homepage.recently_uploaded.document.keyword_missing')).html_safe %>
-
+
+
+ <%= t('hyrax.homepage.recently_uploaded.document.keyword_label') %>: <%= link_to_facet_list(recent_document.keyword, 'keyword', t('hyrax.homepage.recently_uploaded.document.keyword_missing')).html_safe %>
+
+
diff --git a/app/views/layouts/_head_tag_content.html.erb b/app/views/layouts/_head_tag_content.html.erb
index beb55fa2..31afde45 100644
--- a/app/views/layouts/_head_tag_content.html.erb
+++ b/app/views/layouts/_head_tag_content.html.erb
@@ -12,8 +12,8 @@ signed in %>
<%= yield :twitter_meta %>
-
-<%= yield :gscholar_meta %>
+
+<%= yield :schoolie_meta %>
<%= content_for?(:page_title) ? yield(:page_title) : default_page_title %>
diff --git a/app/views/shared/_citations.html.erb b/app/views/shared/_citations.html.erb
new file mode 100644
index 00000000..49a8b09d
--- /dev/null
+++ b/app/views/shared/_citations.html.erb
@@ -0,0 +1,2 @@
+<%= render 'shared/twitter_citations' %>
+<%= render 'shared/schoolie_citations' %>
\ No newline at end of file
diff --git a/app/views/shared/_schoolie_citations.html.erb b/app/views/shared/_schoolie_citations.html.erb
new file mode 100644
index 00000000..9bff92ec
--- /dev/null
+++ b/app/views/shared/_schoolie_citations.html.erb
@@ -0,0 +1,5 @@
+<% content_for(:schoolie_meta) do %>
+ <% if @presenter.scholarly? %>
+ <%schoolie_tags(@presenter).html_safe%>
+ <% end %>
+<% end %>
diff --git a/app/views/shared/_twitter_citations.html.erb b/app/views/shared/_twitter_citations.html.erb
new file mode 100644
index 00000000..a9afc0b9
--- /dev/null
+++ b/app/views/shared/_twitter_citations.html.erb
@@ -0,0 +1,15 @@
+<% content_for(:twitter_meta) do %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+<% end %>
diff --git a/config/authorities/resource_types.yml b/config/authorities/resource_types.yml
index d33950ed..5d90ef40 100644
--- a/config/authorities/resource_types.yml
+++ b/config/authorities/resource_types.yml
@@ -15,12 +15,16 @@ terms:
term: Conference Proceeding
- id: Dataset
term: Dataset
+ - id: Dissertation
+ term: Dissertation
- id: Image
term: Image
- id: Journal
term: Journal
- id: Map or Cartographic Material
term: Map or Cartographic Material
+ - id: Master's Thesis
+ term: Master's Thesis
- id: Meeting Minutes
term: Meeting Minutes
- id: Newsletter
@@ -39,8 +43,6 @@ terms:
term: Research Paper
- id: Software or Program Code
term: Software or Program Code
- - id: Thesis or Dissertation
- term: Thesis or Dissertation
- id: Video
term: Video
- id: Working Paper
diff --git a/config/etd_degree_map.yml b/config/etd_degree_map.yml
new file mode 100644
index 00000000..5131db02
--- /dev/null
+++ b/config/etd_degree_map.yml
@@ -0,0 +1,20 @@
+Master's Thesis:
+ - M.A.
+ - M.S.
+ - M.P.H.
+ - LL.M.
+ - M.F.A.
+ - M.A.T.
+ - M.P.S.
+ - M.B.A.
+ - M.F.S.
+ - M.Int.St.
+ - M.P.H.
+ - M.P.P.
+Dissertation:
+ - Ph.D.
+ - Ed.D.
+ - D.Engr.
+ - Dr.P.H.
+ - D.Sc.
+ - S.J.D.
diff --git a/config/schoolie.yml b/config/schoolie.yml
new file mode 100644
index 00000000..8d9cc91e
--- /dev/null
+++ b/config/schoolie.yml
@@ -0,0 +1,10 @@
+static:
+ citation_institution: George Washington University
+attributes:
+ citation_title: title
+ citation_author: creator
+ citation_type: resource_type
+ dc.type: resource_type
+ citation_date: publication_date
+ citation_keywords: keyword
+ citation_pdf_url: download_url
diff --git a/config/sitemap.rb b/config/sitemap.rb
deleted file mode 100644
index 5c02484e..00000000
--- a/config/sitemap.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-Sitemap::Generator.instance.load(host: 'scholarspace.library.gwu.edu', protocol: 'https') do
- path :root, priority: 1, change_frequency: 'weekly'
- path :search_catalog, priority: 1, change_frequency: 'weekly'
-
- read_group = ActiveFedora.index_field_mapper.solr_name('read_access_group', :symbol)
- GwWork.where(read_group => 'public').each do |f|
- literal Rails.application.routes.url_helpers.hyrax_gw_work_path(f, action: 'show'),
- priority: 1, change_frequency: 'weekly'
- end
- GwEtd.where(read_group => 'public').each do |f|
- literal Rails.application.routes.url_helpers.hyrax_gw_etd_path(f, action: 'show'),
- priority: 1, change_frequency: 'weekly'
- end
-end
diff --git a/lib/tasks/gwss.rake b/lib/tasks/gwss.rake
index 2070d141..f7ec4956 100644
--- a/lib/tasks/gwss.rake
+++ b/lib/tasks/gwss.rake
@@ -20,9 +20,9 @@ namespace :gwss do
end
end
- desc "Queues a job to (re)generate the sitemap.xml"
+ desc "Executes (immediately) a job to (re)generate the sitemap.xml"
task "sitemap_queue_generate" => :environment do
- SitemapRegenerateJob.perform_later
+ SitemapRegenerateJob.perform_now
end
desc "Creates the default Admin Set if it doesn't exist"
@@ -141,6 +141,10 @@ namespace :gwss do
# problem that would be caused by referencing GwEtd first
# See articles such as http://neethack.com/2015/04/rails-circular-dependency/
GwWork
+
+ degree_hash = YAML.load_file('config/etd_degree_map.yml')
+ degree_categories = degree_hash.keys # Typically ["Master's Thesis", "Dissertation"]
+
manifest_file = options[:mfpath]
if File.exist?(manifest_file)
mf = File.read(manifest_file)
@@ -153,7 +157,10 @@ namespace :gwss do
item_attributes['degree'] = manifest_json['degree'][0]
end
# resource_type may need more logic around it, TBD
- item_attributes['resource_type'] = ['Thesis or Dissertation']
+ if manifest_json['etd_type']
+ item_attributes['resource_type'] = manifest_json['etd_type']
+ end
+ # item_attributes['resource_type'] = ['Thesis or Dissertation']
# dc:rights
# Always set this license for ETDs
@@ -313,4 +320,48 @@ namespace :gwss do
ContentBlock.find_or_create_by(name: "help_page").update!(value: help_page_html.read)
ContentBlock.find_or_create_by(name: "share_page").update!(value: share_page_html.read)
end
+
+ desc "Reassigns GwEtd resource_type values to Master's Thesis or Dissertation"
+ task "reassign_etd_resource_types" => :environment do
+ etd_degree_map = YAML.load_file('config/etd_degree_map.yml')
+ degree_etd_map = {}
+ degree_categories = etd_degree_map.keys
+ # Flip etd_degree_map to create degree_etd_map
+ # So that for any given degree, we can get back whether it's a masters or a doctorate
+ degree_categories.each do |degree_category|
+ etd_degree_map[degree_category].each do |degree_name|
+ # upcase each degree (just in case) and ignore "."s
+ degree_etd_map[degree_name.upcase.delete('.')] = degree_category
+ end
+ end
+
+ ids = Hyrax::SolrService.new.get("has_model_ssim:GwEtd", fl: [:id], rows: 1_000_000)
+ ids["response"]["docs"].each do |doc|
+ work = GwEtd.find(doc["id"])
+ if work.degree.nil?
+ puts "GwEtd id=#{doc["id"]} degree is empty! Skipping"
+ else
+ degree_name = work.degree.upcase.delete('.')
+ if degree_etd_map.keys.include?(degree_name)
+ work.resource_type = [degree_etd_map[degree_name]]
+ work.save
+ puts "Reassigned #{degree_name} resource type to #{degree_etd_map[degree_name]}"
+ else
+ puts "Degree name #{degree_name} not found! Skipping"
+ end
+ end
+ end
+ end
+
+ desc "Enumerates degree types present among existing GwEtd works"
+ task "enumerate_degree_types" => :environment do
+ ids = Hyrax::SolrService.new.get("has_model_ssim:GwEtd", fl: [:id], rows: 1_000_000)
+ docs = ids["response"]["docs"]
+ # Map a list of ids to a list of degree values
+ degrees = docs.map {|doc| GwEtd.find(doc["id"]).degree}
+ degree_hash = degrees.tally
+ degree_hash.keys.each do |key|
+ puts "#{key}, #{degree_hash[key]}"
+ end
+ end
end
diff --git a/lib/tasks/schoolie.rake b/lib/tasks/schoolie.rake
new file mode 100644
index 00000000..62b50ce0
--- /dev/null
+++ b/lib/tasks/schoolie.rake
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'json'
+require 'nokogiri'
+
+namespace :schoolie do
+ desc "Creates Google Scholar compliant sitemap for GwEtd works"
+ task sitemap: :environment do
+ date_field = 'system_modified_dtsi'
+ result = Hyrax::SolrService.new.get("has_model_ssim:GwEtd",
+ fl: "id,#{date_field}",
+ rows: 1_000_000)
+ ids = result['response']['docs'].map do |x|
+ ["https://scholarspace.library.gwu.edu/etd/#{x['id'].to_s}", x[date_field].to_s]
+ end
+ builder = Nokogiri::XML::Builder.new do |sitemap|
+ sitemap.urlset("xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
+ xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
+ "xsi:schemaLocation": "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd") {
+ ids.each { |url, date|
+ sitemap.url {
+ sitemap.loc url
+ sitemap.lastmod date
+ }
+ }
+ }
+ end
+ File.open(Rails.root.join("public", "sitemap.xml"), "w") { |f| f.write(builder.to_xml) }
+ end
+end