geoblacklight_admin 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +24 -11
- data/Rakefile +83 -47
- data/app/assets/javascripts/geoblacklight_admin/chosen.js +1 -0
- data/app/assets/stylesheets/geoblacklight_admin/_core.scss +24 -0
- data/app/assets/stylesheets/geoblacklight_admin/modules/_nav.scss +0 -5
- data/app/assets/stylesheets/geoblacklight_admin/modules/_tables.scss +1 -1
- data/app/controllers/admin/admin_controller.rb +16 -0
- data/app/controllers/admin/advanced_search_controller.rb +7 -1
- data/app/controllers/admin/assets_controller.rb +47 -32
- data/app/controllers/admin/bookmarks_controller.rb +17 -5
- data/app/controllers/admin/bulk_actions_controller.rb +32 -1
- data/app/controllers/admin/document_accesses_controller.rb +38 -0
- data/app/controllers/admin/document_assets_controller.rb +47 -89
- data/app/controllers/admin/document_distributions_controller.rb +172 -0
- data/app/controllers/admin/documents_controller.rb +43 -57
- data/app/controllers/admin/elements_controller.rb +24 -0
- data/app/controllers/admin/form_elements_controller.rb +33 -0
- data/app/controllers/admin/ids_controller.rb +6 -0
- data/app/controllers/admin/import_documents_controller.rb +11 -1
- data/app/controllers/admin/imports_controller.rb +34 -4
- data/app/controllers/admin/mappings_controller.rb +15 -0
- data/app/controllers/admin/notifications_controller.rb +27 -0
- data/app/controllers/admin/reference_types_controller.rb +106 -0
- data/app/controllers/admin/search_controller.rb +7 -0
- data/app/controllers/admin/users_controller.rb +10 -0
- data/app/helpers/asset_helper.rb +6 -0
- data/app/helpers/bulk_actions_helper.rb +10 -1
- data/app/helpers/document_helper.rb +36 -0
- data/app/helpers/geoblacklight_admin_helper.rb +88 -8
- data/app/helpers/mappings_helper.rb +26 -0
- data/app/indexers/document_indexer.rb +22 -2
- data/app/javascript/channels/consumer.js +6 -0
- data/app/javascript/channels/export_channel.js +30 -0
- data/app/javascript/channels/index.js +3 -0
- data/app/javascript/controllers/results_controller.js +14 -0
- data/app/javascript/index.js +8 -2
- data/app/jobs/bulk_action_revert_document_job.rb +4 -12
- data/app/jobs/bulk_action_run_document_job.rb +2 -10
- data/app/jobs/export_job.rb +35 -8
- data/app/jobs/geoblacklight_admin/delete_thumbnail_job.rb +19 -0
- data/app/jobs/geoblacklight_admin/remove_parent_dct_references_uri_job.rb +16 -0
- data/app/jobs/geoblacklight_admin/set_parent_dct_references_uri_job.rb +17 -0
- data/app/jobs/geoblacklight_admin/store_image_job.rb +22 -0
- data/app/jobs/import_document_job.rb +1 -4
- data/app/jobs/import_run_job.rb +1 -1
- data/app/models/admin/bookmark.rb +1 -1
- data/app/models/asset.rb +20 -0
- data/app/models/bulk_action.rb +2 -1
- data/app/models/bulk_actions/change_publication_state.rb +0 -25
- data/app/models/bulk_actions/delete_thumbnails.rb +6 -0
- data/app/models/bulk_actions/draft_document.rb +6 -0
- data/app/models/bulk_actions/harvest_thumbnails.rb +6 -0
- data/app/models/bulk_actions/publish_document.rb +6 -0
- data/app/models/bulk_actions/unpublish_document.rb +6 -0
- data/app/models/document/geom_validator.rb +8 -0
- data/app/models/document/reference.rb +65 -65
- data/app/models/document.rb +129 -72
- data/app/models/document_distribution.rb +145 -0
- data/app/models/element.rb +2 -0
- data/app/models/geoblacklight_admin/schema.rb +10 -2
- data/app/models/import/csv_duplicates_validator.rb +2 -0
- data/app/models/import/csv_header_validator.rb +3 -1
- data/app/models/import_btaa_aardvark.rb +2 -2
- data/app/models/import_document_state_machine.rb +1 -0
- data/app/models/import_gblv1.rb +2 -2
- data/app/models/reference_type.rb +40 -0
- data/app/models/user.rb +4 -2
- data/app/services/export_csv_document_distributions_service.rb +61 -0
- data/app/services/geoblacklight_admin/image_service/iiif_manifest.rb +39 -43
- data/app/services/geoblacklight_admin/image_service/tms.rb +0 -8
- data/app/services/geoblacklight_admin/image_service.rb +1 -1
- data/app/services/geoblacklight_admin/item_viewer.rb +4 -4
- data/app/views/admin/bookmarks/index.html.erb +19 -14
- data/app/views/admin/bulk_actions/show.html.erb +1 -1
- data/app/views/admin/document_accesses/import.html.erb +6 -2
- data/app/views/admin/document_assets/_assets_table.html.erb +49 -0
- data/app/views/admin/document_assets/_form.html.erb +2 -3
- data/app/views/admin/document_assets/index.html.erb +1 -47
- data/app/views/admin/document_distributions/_document_distribution.html.erb +39 -0
- data/app/views/admin/document_distributions/_document_distribution.json.jbuilder +2 -0
- data/app/views/admin/document_distributions/_form.html.erb +34 -0
- data/app/views/admin/document_distributions/destroy_all.html.erb +82 -0
- data/app/views/admin/document_distributions/edit.html.erb +12 -0
- data/app/views/admin/document_distributions/import.html.erb +80 -0
- data/app/views/admin/document_distributions/index.html.erb +143 -0
- data/app/views/admin/document_distributions/index.json.jbuilder +1 -0
- data/app/views/admin/document_distributions/new.html.erb +11 -0
- data/app/views/admin/document_distributions/show.html.erb +10 -0
- data/app/views/admin/document_distributions/show.json.jbuilder +1 -0
- data/app/views/admin/documents/_document.html.erb +1 -3
- data/app/views/admin/documents/_form.html.erb +2 -4
- data/app/views/admin/documents/_form_control.html.erb +5 -2
- data/app/views/admin/documents/_form_nav.html.erb +14 -5
- data/app/views/admin/documents/_form_nav_kithe.html.erb +4 -1
- data/app/views/admin/documents/_json_aardvark.jbuilder +1 -1
- data/app/views/admin/documents/_json_gbl_v1.jbuilder +1 -1
- data/app/views/admin/documents/_result_selected_options.html.erb +5 -2
- data/app/views/admin/documents/admin.html.erb +5 -5
- data/app/views/admin/documents/features/_document_references.html.erb +23 -0
- data/app/views/admin/documents/features/_multiple_download_links.html.erb +29 -26
- data/app/views/admin/ids/fetch.json.jbuilder +0 -2
- data/app/views/admin/ids/index.json.jbuilder +0 -2
- data/app/views/admin/imports/_form.html.erb +1 -1
- data/app/views/admin/imports/show.html.erb +1 -1
- data/app/views/admin/layouts/application.html.erb +4 -2
- data/app/views/admin/mappings/index.html.erb +1 -1
- data/app/views/admin/notifications/_notification.html.haml +29 -28
- data/app/views/admin/reference_types/_form.html.erb +25 -0
- data/app/views/admin/reference_types/_reference_type.html.erb +52 -0
- data/app/views/admin/reference_types/_reference_type.json.jbuilder +2 -0
- data/app/views/admin/reference_types/edit.html.erb +12 -0
- data/app/views/admin/reference_types/index.html.erb +52 -0
- data/app/views/admin/reference_types/index.json.jbuilder +1 -0
- data/app/views/admin/reference_types/new.html.erb +11 -0
- data/app/views/admin/reference_types/show.html.erb +3 -0
- data/app/views/admin/reference_types/show.json.jbuilder +1 -0
- data/app/views/admin/shared/_footer.html.erb +5 -2
- data/app/views/admin/shared/_js_behaviors.html.erb +2 -3
- data/app/views/admin/shared/_navbar.html.erb +9 -2
- data/app/views/admin/users/index.html.erb +0 -1
- data/app/views/catalog/_show_gbl_admin.html.erb +1 -1
- data/config/initializers/defaults.yml +310 -0
- data/config/initializers/rails_config.rb +8 -0
- data/config/locales/documents.en.yml +14 -0
- data/config/routes.rb +30 -5
- data/db/import_references_schema_support.numbers +0 -0
- data/db/migrate/20230316183001_add_geoblacklight_admin_gem.rb +0 -12
- data/db/migrate/20241009200524_create_admin_reference_types.rb +13 -0
- data/db/migrate/20241010161420_create_document_references.rb +14 -0
- data/db/migrate/20241120238823_rename_references_to_distributions.rb +5 -0
- data/db/seeds.rb +5 -0
- data/db/seeds_elements.csv +1 -1
- data/db/seeds_elements.numbers +0 -0
- data/db/seeds_reference_types.csv +29 -0
- data/db/seeds_reference_types.numbers +0 -0
- data/db/structure.sql +1 -38
- data/lib/compose.yml +31 -0
- data/lib/generators/geoblacklight_admin/config_generator.rb +53 -12
- data/lib/generators/geoblacklight_admin/install_generator.rb +8 -0
- data/lib/generators/geoblacklight_admin/templates/btaa_sample_records.csv +5 -0
- data/lib/generators/geoblacklight_admin/templates/config/database.yml +1 -1
- data/lib/generators/geoblacklight_admin/templates/config/initializers/devise.rb +0 -2
- data/lib/generators/geoblacklight_admin/templates/config/initializers/mime_types.rb +1 -0
- data/lib/generators/geoblacklight_admin/templates/demo-app/Dockerfile +31 -0
- data/lib/generators/geoblacklight_admin/templates/demo-app/compose.yml +42 -0
- data/lib/generators/geoblacklight_admin/templates/demo-app/start-server.sh +21 -0
- data/lib/geoblacklight_admin/engine.rb +4 -0
- data/lib/geoblacklight_admin/rake_task.rb +2 -0
- data/lib/geoblacklight_admin/tasks/distributions.rake +69 -0
- data/lib/geoblacklight_admin/tasks/images.rake +1 -0
- data/lib/geoblacklight_admin/tasks/solr.rake +31 -0
- data/lib/geoblacklight_admin/version.rb +1 -1
- data/lib/geoblacklight_admin.rb +4 -0
- metadata +137 -53
- data/app/helpers/import_documents_helper.rb +0 -5
- data/app/javascript/entrypoints/engine.js +0 -8
- data/config/locales/devise_invitable.en.yml +0 -31
- data/lib/generators/geoblacklight_admin/templates/devise/invitations/edit.html.erb +0 -15
- data/lib/generators/geoblacklight_admin/templates/devise/invitations/new.html.erb +0 -15
- data/lib/generators/geoblacklight_admin/templates/devise/mailer/invitation_instructions.html.erb +0 -11
- data/lib/generators/geoblacklight_admin/templates/devise/mailer/invitation_instructions.text.erb +0 -11
@@ -1,14 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Admin::NotificationsController
|
4
|
+
#
|
5
|
+
# This controller manages the notifications for the admin panel. It provides
|
6
|
+
# actions to list, update, destroy, and batch update notifications.
|
4
7
|
module Admin
|
5
8
|
class NotificationsController < Admin::AdminController
|
6
9
|
before_action :set_notification, only: %i[update destroy]
|
7
10
|
|
11
|
+
# GET /admin/notifications
|
12
|
+
#
|
13
|
+
# Lists all notifications for the current user, paginated.
|
14
|
+
#
|
15
|
+
# @return [void]
|
8
16
|
def index
|
9
17
|
@pagy, @notifications = pagy(current_user.notifications.order(created_at: :desc), items: 20)
|
10
18
|
end
|
11
19
|
|
20
|
+
# PATCH/PUT /admin/notifications/:id
|
21
|
+
#
|
22
|
+
# Updates the read status of a notification.
|
23
|
+
#
|
24
|
+
# @param [String] read The read status, "0" for unread, "1" for read.
|
25
|
+
# @return [void]
|
12
26
|
def update
|
13
27
|
case params[:read]
|
14
28
|
when "0"
|
@@ -25,6 +39,11 @@ module Admin
|
|
25
39
|
end
|
26
40
|
end
|
27
41
|
|
42
|
+
# DELETE /admin/notifications/:id
|
43
|
+
#
|
44
|
+
# Destroys a notification and purges its associated file.
|
45
|
+
#
|
46
|
+
# @return [void]
|
28
47
|
def destroy
|
29
48
|
@notification.file.purge
|
30
49
|
@notification.destroy
|
@@ -34,6 +53,11 @@ module Admin
|
|
34
53
|
end
|
35
54
|
end
|
36
55
|
|
56
|
+
# POST /admin/notifications/batch
|
57
|
+
#
|
58
|
+
# Marks all notifications as read.
|
59
|
+
#
|
60
|
+
# @return [void]
|
37
61
|
def batch
|
38
62
|
return unless params[:read] == "all"
|
39
63
|
|
@@ -44,6 +68,9 @@ module Admin
|
|
44
68
|
|
45
69
|
private
|
46
70
|
|
71
|
+
# Sets the notification based on the provided ID.
|
72
|
+
#
|
73
|
+
# @return [void]
|
47
74
|
def set_notification
|
48
75
|
@notification = Notification.find(params[:id])
|
49
76
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Admin::ReferenceTypesController
|
4
|
+
#
|
5
|
+
# This controller manages the CRUD operations for ReferenceType objects
|
6
|
+
# within the admin namespace. It includes actions to list, show, create,
|
7
|
+
# update, and destroy reference types, as well as a custom sort action.
|
8
|
+
class Admin::ReferenceTypesController < Admin::AdminController
|
9
|
+
before_action :set_reference_type, only: %i[show edit update destroy]
|
10
|
+
|
11
|
+
# GET /admin/reference_types or /admin/reference_types.json
|
12
|
+
#
|
13
|
+
# Lists all reference types.
|
14
|
+
def index
|
15
|
+
@reference_types = ReferenceType.all
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET /admin/reference_types/1 or /admin/reference_types/1.json
|
19
|
+
#
|
20
|
+
# Shows a specific reference type.
|
21
|
+
def show
|
22
|
+
end
|
23
|
+
|
24
|
+
# GET /admin/reference_types/new
|
25
|
+
#
|
26
|
+
# Initializes a new reference type.
|
27
|
+
def new
|
28
|
+
@reference_type = ReferenceType.new
|
29
|
+
end
|
30
|
+
|
31
|
+
# GET /admin/reference_types/1/edit
|
32
|
+
#
|
33
|
+
# Edits an existing reference type.
|
34
|
+
def edit
|
35
|
+
end
|
36
|
+
|
37
|
+
# POST /admin/reference_types or /admin/reference_types.json
|
38
|
+
#
|
39
|
+
# Creates a new reference type. If successful, redirects to the show page
|
40
|
+
# of the newly created reference type. Otherwise, re-renders the new form.
|
41
|
+
def create
|
42
|
+
@reference_type = ReferenceType.new(reference_type_params)
|
43
|
+
|
44
|
+
respond_to do |format|
|
45
|
+
if @reference_type.save
|
46
|
+
format.html { redirect_to admin_reference_type_path(@reference_type), notice: "Reference type was successfully created." }
|
47
|
+
format.json { render :show, status: :created, location: @reference_type }
|
48
|
+
else
|
49
|
+
format.html { render :new, status: :unprocessable_entity }
|
50
|
+
format.json { render json: @reference_type.errors, status: :unprocessable_entity }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# PATCH/PUT /admin/reference_types/1 or /admin/reference_types/1.json
|
56
|
+
#
|
57
|
+
# Updates an existing reference type. If successful, redirects to the show
|
58
|
+
# page of the updated reference type. Otherwise, re-renders the edit form.
|
59
|
+
def update
|
60
|
+
respond_to do |format|
|
61
|
+
if @reference_type.update(reference_type_params)
|
62
|
+
format.html { redirect_to admin_reference_type_path(@reference_type), notice: "Reference type was successfully updated." }
|
63
|
+
format.json { render :show, status: :ok, location: @reference_type }
|
64
|
+
else
|
65
|
+
format.html { render :edit, status: :unprocessable_entity }
|
66
|
+
format.json { render json: @reference_type.errors, status: :unprocessable_entity }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# DELETE /admin/reference_types/1 or /admin/reference_types/1.json
|
72
|
+
#
|
73
|
+
# Destroys a reference type. Redirects to the index page with a notice.
|
74
|
+
def destroy
|
75
|
+
@reference_type.destroy!
|
76
|
+
|
77
|
+
respond_to do |format|
|
78
|
+
format.html { redirect_to admin_reference_types_path, status: :see_other, notice: "Reference type was successfully destroyed." }
|
79
|
+
format.json { head :no_content }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# POST /admin/reference_types/sort
|
84
|
+
#
|
85
|
+
# Sorts reference types based on the provided list of IDs.
|
86
|
+
def sort
|
87
|
+
ReferenceType.sort_elements(params[:id_list])
|
88
|
+
render body: nil
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Use callbacks to share common setup or constraints between actions.
|
94
|
+
#
|
95
|
+
# Sets the @reference_type instance variable for actions that require it.
|
96
|
+
def set_reference_type
|
97
|
+
@reference_type = ReferenceType.find(params[:id])
|
98
|
+
end
|
99
|
+
|
100
|
+
# Only allow a list of trusted parameters through.
|
101
|
+
#
|
102
|
+
# Permits the parameters required for creating or updating a reference type.
|
103
|
+
def reference_type_params
|
104
|
+
params.require(:reference_type).permit(:name, :reference_type, :reference_uri, :label, :note, :position)
|
105
|
+
end
|
106
|
+
end
|
@@ -1,8 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Admin::SearchController
|
4
|
+
# This controller handles search-related actions for the admin interface.
|
4
5
|
module Admin
|
5
6
|
class SearchController < Admin::AdminController
|
7
|
+
# GET /admin/search
|
8
|
+
#
|
9
|
+
# This action sets up the request URL and retrieves facet options
|
10
|
+
# from the Blacklight API.
|
11
|
+
#
|
12
|
+
# @return [void]
|
6
13
|
def index
|
7
14
|
@request = "#{request.protocol}#{request.host}:#{request.port}"
|
8
15
|
@facet_options = BlacklightApiFacets.new(@request).facets
|
@@ -1,8 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Admin::UsersController
|
4
|
+
#
|
5
|
+
# This controller handles the actions related to admin users.
|
6
|
+
# It inherits from Admin::AdminController, which provides
|
7
|
+
# common functionality for all admin-related controllers.
|
4
8
|
module Admin
|
5
9
|
class UsersController < Admin::AdminController
|
10
|
+
# GET /admin/users
|
11
|
+
#
|
12
|
+
# This action retrieves all users with admin privileges.
|
13
|
+
# It assigns the result to the @users instance variable,
|
14
|
+
# which can be used in the corresponding view to display
|
15
|
+
# the list of admin users.
|
6
16
|
def index
|
7
17
|
@users = User.where(admin: true)
|
8
18
|
end
|
data/app/helpers/asset_helper.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# AssetHelper
|
4
|
+
#
|
5
|
+
# This module provides helper methods for asset management.
|
4
6
|
module AssetHelper
|
7
|
+
# Determines if an asset has a thumbnail to render.
|
8
|
+
#
|
9
|
+
# @param asset [Object] The asset object to check.
|
10
|
+
# @return [Boolean] Returns true if the asset has a file URL and file derivatives present, otherwise false.
|
5
11
|
def asset_thumb_to_render?(asset)
|
6
12
|
asset&.file_url&.present? && asset&.file_derivatives&.present?
|
7
13
|
end
|
@@ -1,9 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# BulkActionsHelper
|
4
|
+
#
|
5
|
+
# This module provides helper methods for handling bulk actions
|
6
|
+
# within the GeoblacklightAdmin application.
|
4
7
|
module BulkActionsHelper
|
8
|
+
# Returns a collection of attributes that can be used for bulk actions.
|
9
|
+
#
|
10
|
+
# The collection includes all importable fields from the GeoblacklightAdmin
|
11
|
+
# schema, with "Publication State" prepended to the list.
|
12
|
+
#
|
13
|
+
# @return [Array<String>] an array of attribute names
|
5
14
|
def bulk_actions_collection
|
6
|
-
attrs =
|
15
|
+
attrs = GeoblacklightAdmin::Schema.instance.importable_fields.collect { |key, _value| key }
|
7
16
|
attrs.prepend("Publication State")
|
8
17
|
end
|
9
18
|
end
|
@@ -1,7 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# DocumentHelper
|
4
|
+
#
|
5
|
+
# This module provides helper methods for handling document-related
|
6
|
+
# functionalities such as generating publication state badges, creating
|
7
|
+
# localized links, and handling pagination links.
|
4
8
|
module DocumentHelper
|
9
|
+
# Generates a badge for the publication state of a document.
|
10
|
+
#
|
11
|
+
# @param document [Object] the document object containing the publication state
|
12
|
+
# @return [String] HTML link with a span element representing the publication state
|
5
13
|
def publication_state_badge(document)
|
6
14
|
case document.publication_state
|
7
15
|
when "draft"
|
@@ -19,15 +27,27 @@ module DocumentHelper
|
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
30
|
+
# Localizes a given link by parsing its URI and appending it to a base path.
|
31
|
+
#
|
32
|
+
# @param link [String] the link to be localized
|
33
|
+
# @return [String] the localized link
|
22
34
|
def localize_link(link)
|
23
35
|
uri = URI.parse(link)
|
24
36
|
"/admin/documents?#{uri.query}"
|
25
37
|
end
|
26
38
|
|
39
|
+
# Creates a sort link with a label and localized URL.
|
40
|
+
#
|
41
|
+
# @param link [Hash] a hash containing link attributes and self link
|
42
|
+
# @return [String] HTML link element for sorting
|
27
43
|
def sort_link(link)
|
28
44
|
link_to link["attributes"]["label"], localize_link(link["links"]["self"]), {class: "dropdown-item"}
|
29
45
|
end
|
30
46
|
|
47
|
+
# Processes a link from an API response, determining whether to add or remove a facet.
|
48
|
+
#
|
49
|
+
# @param link [Hash] a hash containing links for adding or removing facets
|
50
|
+
# @return [Hash] a hash with action and link keys
|
31
51
|
def link_from_api(link)
|
32
52
|
# Append facet - Full URI returned
|
33
53
|
uri = URI.parse(link["links"]["self"])
|
@@ -38,6 +58,10 @@ module DocumentHelper
|
|
38
58
|
{action: "remove", link: "/admin/documents?#{uri.query}"}
|
39
59
|
end
|
40
60
|
|
61
|
+
# Generates a link to the previous page in a paginated list.
|
62
|
+
#
|
63
|
+
# @param links [Hash] a hash containing pagination links
|
64
|
+
# @return [String] HTML link element for the previous page
|
41
65
|
def previous_link(links)
|
42
66
|
if links["prev"]
|
43
67
|
link_to "Previous", localize_link(links["prev"]), {class: "btn btn-outline-primary btn-sm"}
|
@@ -46,6 +70,10 @@ module DocumentHelper
|
|
46
70
|
end
|
47
71
|
end
|
48
72
|
|
73
|
+
# Generates a link to the next page in a paginated list.
|
74
|
+
#
|
75
|
+
# @param links [Hash] a hash containing pagination links
|
76
|
+
# @return [String] HTML link element for the next page
|
49
77
|
def next_link(links)
|
50
78
|
if links["next"]
|
51
79
|
link_to "Next", localize_link(links["next"]), {class: "btn btn-outline-primary btn-sm"}
|
@@ -54,10 +82,18 @@ module DocumentHelper
|
|
54
82
|
end
|
55
83
|
end
|
56
84
|
|
85
|
+
# Constructs a link to a document's page in the Blacklight catalog.
|
86
|
+
#
|
87
|
+
# @param document [Object] the document object
|
88
|
+
# @return [String] the URL to the document's Blacklight catalog page
|
57
89
|
def blacklight_link(document)
|
58
90
|
"#{BLACKLIGHT_URL}/catalog/#{document.friendlier_id}"
|
59
91
|
end
|
60
92
|
|
93
|
+
# Determines if a document's thumbnail should be rendered.
|
94
|
+
#
|
95
|
+
# @param document [Object] the document object
|
96
|
+
# @return [Boolean] true if the thumbnail should be rendered, false otherwise
|
61
97
|
def thumb_to_render?(document)
|
62
98
|
document&.thumbnail&.file_url&.present? && document&.thumbnail&.file_derivatives&.present?
|
63
99
|
end
|
@@ -1,13 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# GeoblacklightAdminHelper
|
4
|
+
#
|
5
|
+
# This module provides helper methods for the GeoBlacklight admin interface.
|
6
|
+
# It includes methods for handling JSON data, generating paths, formatting
|
7
|
+
# flash messages, and more.
|
4
8
|
module GeoblacklightAdminHelper
|
5
9
|
# @TODO:
|
6
10
|
# Cannot generate app if uncommented...
|
7
11
|
# Uncomment after app is generated to fix view errors
|
8
12
|
include ::Pagy::Frontend if defined?(Pagy)
|
9
13
|
|
10
|
-
#
|
14
|
+
# Removes blank values from JSON data.
|
15
|
+
#
|
16
|
+
# @param value [String, Array] the value to check for presence
|
17
|
+
# @return [String, Array, nil] the original value if present, otherwise nil
|
11
18
|
def no_json_blanks(value)
|
12
19
|
case value
|
13
20
|
when String
|
@@ -17,17 +24,21 @@ module GeoblacklightAdminHelper
|
|
17
24
|
end
|
18
25
|
end
|
19
26
|
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
27
|
+
# Generates a search path for the QA (questioning_authority) gem.
|
28
|
+
#
|
29
|
+
# @param vocab [String] the vocabulary to search
|
30
|
+
# @param subauthority [String, nil] the subauthority to search
|
31
|
+
# @return [String] the generated search path
|
23
32
|
def qa_search_vocab_path(vocab, subauthority = nil)
|
24
33
|
path = "/authorities/search/#{CGI.escape vocab}"
|
25
|
-
|
26
34
|
path += "/#{CGI.escape subauthority}" if subauthority
|
27
|
-
|
28
35
|
path
|
29
36
|
end
|
30
37
|
|
38
|
+
# Maps flash message levels to CSS classes.
|
39
|
+
#
|
40
|
+
# @param level [String] the flash message level
|
41
|
+
# @return [String] the corresponding CSS class
|
31
42
|
def flash_class(level)
|
32
43
|
alerts = {
|
33
44
|
"notice" => "alert alert-info",
|
@@ -38,6 +49,9 @@ module GeoblacklightAdminHelper
|
|
38
49
|
alerts[level]
|
39
50
|
end
|
40
51
|
|
52
|
+
# Provides a mapping of institution codes to institution names.
|
53
|
+
#
|
54
|
+
# @return [Hash] a hash mapping institution codes to names
|
41
55
|
def b1g_institution_codes
|
42
56
|
{
|
43
57
|
"01" => "Indiana University",
|
@@ -58,11 +72,17 @@ module GeoblacklightAdminHelper
|
|
58
72
|
}
|
59
73
|
end
|
60
74
|
|
75
|
+
# Generates an HTML badge for bookmarks.
|
76
|
+
#
|
77
|
+
# @return [String] the HTML string for the bookmarks badge
|
61
78
|
def bookmarks_badge
|
62
79
|
bookmarks_classes = ["badge", "badge-dark"]
|
63
80
|
"<span class='#{bookmarks_classes.join(" ")}' id='bookmarks-count'>#{current_user.bookmarks.size}</span>"
|
64
81
|
end
|
65
82
|
|
83
|
+
# Generates an HTML badge for notifications.
|
84
|
+
#
|
85
|
+
# @return [String] the HTML string for the notifications badge
|
66
86
|
def notifications_badge
|
67
87
|
notifications_classes = ["badge"]
|
68
88
|
notifications_classes << "badge-dark" if current_user.notifications.unread.empty?
|
@@ -70,7 +90,10 @@ module GeoblacklightAdminHelper
|
|
70
90
|
"<span class='#{notifications_classes.join(" ")}' id='notification-count'>#{current_user.notifications.unread.size}</span>"
|
71
91
|
end
|
72
92
|
|
73
|
-
#
|
93
|
+
# Converts parameters into hidden form fields.
|
94
|
+
#
|
95
|
+
# @param params [Hash] the parameters to convert
|
96
|
+
# @return [String] the HTML string of hidden fields
|
74
97
|
def params_as_hidden_fields(params)
|
75
98
|
hidden_fields = []
|
76
99
|
flatten_hash(params).each do |name, value|
|
@@ -83,6 +106,12 @@ module GeoblacklightAdminHelper
|
|
83
106
|
safe_join(hidden_fields, "\n")
|
84
107
|
end
|
85
108
|
|
109
|
+
# Flattens a nested hash into a single-level hash with keys representing the
|
110
|
+
# nested structure.
|
111
|
+
#
|
112
|
+
# @param hash [Hash] the hash to flatten
|
113
|
+
# @param ancestor_names [Array] the ancestor keys for nested hashes
|
114
|
+
# @return [Hash] the flattened hash
|
86
115
|
def flatten_hash(hash, ancestor_names = [])
|
87
116
|
flat_hash = {}
|
88
117
|
hash.each do |k, v|
|
@@ -100,6 +129,10 @@ module GeoblacklightAdminHelper
|
|
100
129
|
flat_hash
|
101
130
|
end
|
102
131
|
|
132
|
+
# Generates a key for a flattened hash from an array of names.
|
133
|
+
#
|
134
|
+
# @param names [Array] the array of names
|
135
|
+
# @return [String] the generated key
|
103
136
|
def flat_hash_key(names)
|
104
137
|
names = Array.new(names)
|
105
138
|
name = names.shift.to_s.dup
|
@@ -109,6 +142,10 @@ module GeoblacklightAdminHelper
|
|
109
142
|
name
|
110
143
|
end
|
111
144
|
|
145
|
+
# Maps a character to a CSS class for diff highlighting.
|
146
|
+
#
|
147
|
+
# @param char [String] the character representing a diff operation
|
148
|
+
# @return [String] the corresponding CSS class
|
112
149
|
def diff_class(char)
|
113
150
|
case char
|
114
151
|
when "~"
|
@@ -122,6 +159,10 @@ module GeoblacklightAdminHelper
|
|
122
159
|
end
|
123
160
|
end
|
124
161
|
|
162
|
+
# Generates a link to the admin import page for a given import.
|
163
|
+
#
|
164
|
+
# @param import [Object] the import object
|
165
|
+
# @return [String] the HTML link to the admin import page
|
125
166
|
def link_to_admin_import(import)
|
126
167
|
path = admin_documents_path(
|
127
168
|
{
|
@@ -132,6 +173,12 @@ module GeoblacklightAdminHelper
|
|
132
173
|
link_to import.name, path
|
133
174
|
end
|
134
175
|
|
176
|
+
# Generates a link to the GeoBlacklight import page with optional state.
|
177
|
+
#
|
178
|
+
# @param label [String] the link label
|
179
|
+
# @param import [Object] the import object
|
180
|
+
# @param state [Boolean] the publication state
|
181
|
+
# @return [String] the HTML link to the GeoBlacklight import page
|
135
182
|
def link_to_gbl_import(label, import, state = false)
|
136
183
|
path = if state
|
137
184
|
blacklight_path(
|
@@ -152,7 +199,40 @@ module GeoblacklightAdminHelper
|
|
152
199
|
link_to(label, path)
|
153
200
|
end
|
154
201
|
|
202
|
+
# Generates options for asset DCT references.
|
203
|
+
#
|
204
|
+
# @return [String] the escaped JavaScript string of options
|
155
205
|
def assets_dct_references_options
|
156
|
-
escape_javascript(options_for_select(I18n.t("activemodel.
|
206
|
+
escape_javascript(options_for_select(I18n.t("activemodel.asset_enum_values.document/reference.category").invert.sort.insert(0, ["Choose Reference Type", nil]))).to_s
|
207
|
+
end
|
208
|
+
|
209
|
+
# Determines if a document's thumbnail should be rendered.
|
210
|
+
#
|
211
|
+
# @param document [Object] the document object
|
212
|
+
# @return [Boolean] true if the thumbnail should be rendered, false otherwise
|
213
|
+
def thumb_to_render?(document)
|
214
|
+
if document&.thumbnail&.file_url&.present? && document&.thumbnail&.file_derivatives&.present?
|
215
|
+
true
|
216
|
+
elsif document&.document_assets&.any?
|
217
|
+
document.document_assets.any? do |asset|
|
218
|
+
asset.file_derivatives&.key?(:thumb_standard_2X)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Returns the URL of the thumbnail to render for a document.
|
226
|
+
#
|
227
|
+
# @param document [Object] the document object
|
228
|
+
# @return [String] the URL of the thumbnail to render
|
229
|
+
def thumbnail_to_render(document)
|
230
|
+
if document&.thumbnail&.file_url&.present? && document&.thumbnail&.file_derivatives&.present?
|
231
|
+
document.thumbnail.file_url(:thumb_standard_2X)
|
232
|
+
elsif document&.document_assets&.any?
|
233
|
+
document.document_assets.find do |asset|
|
234
|
+
asset.file_derivatives&.key?(:thumb_standard_2X)
|
235
|
+
end&.file_url(:thumb_standard_2X)
|
236
|
+
end
|
157
237
|
end
|
158
238
|
end
|
@@ -1,7 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# MappingsHelper
|
4
|
+
#
|
5
|
+
# This module provides helper methods for handling mappings in the application.
|
6
|
+
# It includes methods to generate attribute collections and provide mapping
|
7
|
+
# and delimiter suggestions based on import configurations.
|
4
8
|
module MappingsHelper
|
9
|
+
# Returns a collection of attributes that can be used for mapping.
|
10
|
+
#
|
11
|
+
# The collection is generated from importable elements, sorted, and includes
|
12
|
+
# additional options for an empty string and "Discard".
|
13
|
+
#
|
14
|
+
# @return [Array<String>] a sorted array of attribute names with additional options.
|
5
15
|
def attribute_collection
|
6
16
|
attrs = Element.importable.map(&:solr_field).sort
|
7
17
|
attrs.prepend("")
|
@@ -9,6 +19,14 @@ module MappingsHelper
|
|
9
19
|
attrs
|
10
20
|
end
|
11
21
|
|
22
|
+
# Provides a mapping suggestion for a given header based on the import configuration.
|
23
|
+
#
|
24
|
+
# Checks if the header is included in the import's mapping configuration and returns
|
25
|
+
# the destination if available.
|
26
|
+
#
|
27
|
+
# @param import [Object] the import object containing mapping configurations.
|
28
|
+
# @param header [String] the header for which the mapping suggestion is needed.
|
29
|
+
# @return [String, false] the destination mapping if available, otherwise false.
|
12
30
|
def mapping_suggestion(import, header)
|
13
31
|
if import.mapping_configuration.include?(header.to_sym)
|
14
32
|
import.mapping_configuration[header.to_sym][:destination]
|
@@ -17,6 +35,14 @@ module MappingsHelper
|
|
17
35
|
end
|
18
36
|
end
|
19
37
|
|
38
|
+
# Provides a delimiter suggestion for a given header based on the import configuration.
|
39
|
+
#
|
40
|
+
# Checks if the header is included in the import's mapping configuration and returns
|
41
|
+
# the delimiter if available.
|
42
|
+
#
|
43
|
+
# @param import [Object] the import object containing mapping configurations.
|
44
|
+
# @param header [String] the header for which the delimiter suggestion is needed.
|
45
|
+
# @return [String, false] the delimiter if available, otherwise false.
|
20
46
|
def delimiter_suggestion(import, header)
|
21
47
|
if import.mapping_configuration.include?(header.to_sym)
|
22
48
|
import.mapping_configuration[header.to_sym][:delimited]
|
@@ -1,6 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Solr indexing for our document class. Still a work in progress.
|
4
|
+
#
|
5
|
+
# The DocumentIndexer class is responsible for configuring how documents
|
6
|
+
# are indexed into Solr. It uses the Kithe::Indexer framework to map
|
7
|
+
# document attributes to Solr fields.
|
8
|
+
#
|
9
|
+
# The configuration block defines various fields that are indexed, including
|
10
|
+
# fields specific to GeoBlacklight and custom fields defined via the Element model.
|
11
|
+
#
|
12
|
+
# Fields:
|
13
|
+
# - model_pk_ssi: The primary key of the model, extracted from the object's ID.
|
14
|
+
# - gbl_mdVersion_s: A static version string for GeoBlacklight.
|
15
|
+
# - gbl_mdModified_dt: The modification date of the metadata.
|
16
|
+
# - date_created_dtsi: The creation date of the record, in UTC ISO8601 format.
|
17
|
+
# - date_modified_dtsi: The last modification date of the record, in UTC ISO8601 format.
|
18
|
+
# - b1g_geom_import_id_ssi: The import ID for GeoBlacklight administration.
|
19
|
+
#
|
20
|
+
# If the "elements" table exists, additional fields are indexed based on
|
21
|
+
# the Element model's configuration.
|
4
22
|
class DocumentIndexer < Kithe::Indexer
|
5
23
|
configure do
|
6
24
|
# Kithe
|
@@ -12,8 +30,10 @@ class DocumentIndexer < Kithe::Indexer
|
|
12
30
|
# to_field 'geomg_id_s', obj_extract('friendlier_id') # the actual db pk, a UUID
|
13
31
|
|
14
32
|
# Define `to_field`(s) via Element
|
15
|
-
|
16
|
-
|
33
|
+
if ActiveRecord::Base.connection.table_exists?("elements")
|
34
|
+
Element.indexable.each do |elm|
|
35
|
+
to_field elm.solr_field, obj_extract(elm.index_value)
|
36
|
+
end
|
17
37
|
end
|
18
38
|
|
19
39
|
to_field "gbl_mdModified_dt", obj_extract("gbl_mdModified_dt")
|
@@ -0,0 +1,6 @@
|
|
1
|
+
// Action Cable provides the framework to deal with WebSockets in Rails.
|
2
|
+
// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
|
3
|
+
|
4
|
+
import { createConsumer } from "@rails/actioncable"
|
5
|
+
|
6
|
+
export default createConsumer()
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import consumer from "./consumer"
|
2
|
+
|
3
|
+
consumer.subscriptions.create({ channel: "ExportChannel" }, {
|
4
|
+
connected() {
|
5
|
+
// Called when the subscription is ready for use on the server
|
6
|
+
console.log("GBL Admin - ExportChannel connected");
|
7
|
+
},
|
8
|
+
|
9
|
+
disconnected() {
|
10
|
+
// Called when the subscription has been terminated by the server
|
11
|
+
console.log("GBL Admin - ExportChannel disconnected");
|
12
|
+
},
|
13
|
+
|
14
|
+
received(data) {
|
15
|
+
console.log('GBL Admin - ExportChannel received!');
|
16
|
+
console.log(data);
|
17
|
+
|
18
|
+
if (data['progress']) {
|
19
|
+
console.log(data['progress']);
|
20
|
+
}
|
21
|
+
|
22
|
+
if (data['actions']) {
|
23
|
+
for (let index = 0; index < data.actions.length; ++index) {
|
24
|
+
var fnstring = data.actions[index].method;
|
25
|
+
var fn = window["GBLADMIN"][fnstring];
|
26
|
+
if (typeof fn === "function") fn(data.actions[index].payload);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
});
|
@@ -12,6 +12,7 @@ import { Controller } from "stimulus"
|
|
12
12
|
export default class extends Controller {
|
13
13
|
|
14
14
|
connect() {
|
15
|
+
console.log("GBL Admin - ResultsController connected");
|
15
16
|
}
|
16
17
|
|
17
18
|
checkedState(checked, selector='input[type=checkbox]') {
|
@@ -228,6 +229,7 @@ export default class extends Controller {
|
|
228
229
|
}
|
229
230
|
|
230
231
|
exportCsvDocumentDownloads() {
|
232
|
+
console.log('Export - CsvDocumentDownloads')
|
231
233
|
var scope = this.checkSelectionScope();
|
232
234
|
var el = document.querySelector('#result-selected-options');
|
233
235
|
if(scope === 'pageset') {
|
@@ -238,6 +240,7 @@ export default class extends Controller {
|
|
238
240
|
}
|
239
241
|
|
240
242
|
exportCsvDocumentAccessLinks() {
|
243
|
+
console.log('Export - CsvDocumentAccessLinks')
|
241
244
|
var scope = this.checkSelectionScope();
|
242
245
|
var el = document.querySelector('#result-selected-options');
|
243
246
|
if(scope === 'pageset') {
|
@@ -247,6 +250,17 @@ export default class extends Controller {
|
|
247
250
|
}
|
248
251
|
}
|
249
252
|
|
253
|
+
exportCsvDocumentDistributions() {
|
254
|
+
console.log('Export - CsvDocumentDistributions')
|
255
|
+
var scope = this.checkSelectionScope();
|
256
|
+
var el = document.querySelector('#result-selected-options');
|
257
|
+
if(scope === 'pageset') {
|
258
|
+
window.location = el.dataset.pageset + "&format=csv_document_distributions"
|
259
|
+
} else {
|
260
|
+
window.location = el.dataset.resultset + "&format=csv_document_distributions"
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
250
264
|
bulkAction() {
|
251
265
|
var scope = this.checkSelectionScope();
|
252
266
|
var el = document.querySelector('#result-selected-options');
|