geoblacklight_admin 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +24 -11
  3. data/Rakefile +83 -47
  4. data/app/assets/javascripts/geoblacklight_admin/chosen.js +1 -0
  5. data/app/assets/stylesheets/geoblacklight_admin/_core.scss +24 -0
  6. data/app/assets/stylesheets/geoblacklight_admin/modules/_nav.scss +0 -5
  7. data/app/assets/stylesheets/geoblacklight_admin/modules/_tables.scss +1 -1
  8. data/app/controllers/admin/admin_controller.rb +16 -0
  9. data/app/controllers/admin/advanced_search_controller.rb +7 -1
  10. data/app/controllers/admin/assets_controller.rb +47 -32
  11. data/app/controllers/admin/bookmarks_controller.rb +17 -5
  12. data/app/controllers/admin/bulk_actions_controller.rb +32 -1
  13. data/app/controllers/admin/document_accesses_controller.rb +38 -0
  14. data/app/controllers/admin/document_assets_controller.rb +47 -89
  15. data/app/controllers/admin/document_distributions_controller.rb +172 -0
  16. data/app/controllers/admin/documents_controller.rb +43 -57
  17. data/app/controllers/admin/elements_controller.rb +24 -0
  18. data/app/controllers/admin/form_elements_controller.rb +33 -0
  19. data/app/controllers/admin/ids_controller.rb +6 -0
  20. data/app/controllers/admin/import_documents_controller.rb +11 -1
  21. data/app/controllers/admin/imports_controller.rb +34 -4
  22. data/app/controllers/admin/mappings_controller.rb +15 -0
  23. data/app/controllers/admin/notifications_controller.rb +27 -0
  24. data/app/controllers/admin/reference_types_controller.rb +106 -0
  25. data/app/controllers/admin/search_controller.rb +7 -0
  26. data/app/controllers/admin/users_controller.rb +10 -0
  27. data/app/helpers/asset_helper.rb +6 -0
  28. data/app/helpers/bulk_actions_helper.rb +10 -1
  29. data/app/helpers/document_helper.rb +36 -0
  30. data/app/helpers/geoblacklight_admin_helper.rb +88 -8
  31. data/app/helpers/mappings_helper.rb +26 -0
  32. data/app/indexers/document_indexer.rb +22 -2
  33. data/app/javascript/channels/consumer.js +6 -0
  34. data/app/javascript/channels/export_channel.js +30 -0
  35. data/app/javascript/channels/index.js +3 -0
  36. data/app/javascript/controllers/results_controller.js +14 -0
  37. data/app/javascript/index.js +8 -2
  38. data/app/jobs/bulk_action_revert_document_job.rb +4 -12
  39. data/app/jobs/bulk_action_run_document_job.rb +2 -10
  40. data/app/jobs/export_job.rb +35 -8
  41. data/app/jobs/geoblacklight_admin/delete_thumbnail_job.rb +19 -0
  42. data/app/jobs/geoblacklight_admin/remove_parent_dct_references_uri_job.rb +16 -0
  43. data/app/jobs/geoblacklight_admin/set_parent_dct_references_uri_job.rb +17 -0
  44. data/app/jobs/geoblacklight_admin/store_image_job.rb +22 -0
  45. data/app/jobs/import_document_job.rb +1 -4
  46. data/app/jobs/import_run_job.rb +1 -1
  47. data/app/models/admin/bookmark.rb +1 -1
  48. data/app/models/asset.rb +20 -0
  49. data/app/models/bulk_action.rb +2 -1
  50. data/app/models/bulk_actions/change_publication_state.rb +0 -25
  51. data/app/models/bulk_actions/delete_thumbnails.rb +6 -0
  52. data/app/models/bulk_actions/draft_document.rb +6 -0
  53. data/app/models/bulk_actions/harvest_thumbnails.rb +6 -0
  54. data/app/models/bulk_actions/publish_document.rb +6 -0
  55. data/app/models/bulk_actions/unpublish_document.rb +6 -0
  56. data/app/models/document/geom_validator.rb +8 -0
  57. data/app/models/document/reference.rb +65 -65
  58. data/app/models/document.rb +129 -72
  59. data/app/models/document_distribution.rb +145 -0
  60. data/app/models/element.rb +2 -0
  61. data/app/models/geoblacklight_admin/schema.rb +10 -2
  62. data/app/models/import/csv_duplicates_validator.rb +2 -0
  63. data/app/models/import/csv_header_validator.rb +3 -1
  64. data/app/models/import_btaa_aardvark.rb +2 -2
  65. data/app/models/import_document_state_machine.rb +1 -0
  66. data/app/models/import_gblv1.rb +2 -2
  67. data/app/models/reference_type.rb +40 -0
  68. data/app/models/user.rb +4 -2
  69. data/app/services/export_csv_document_distributions_service.rb +61 -0
  70. data/app/services/geoblacklight_admin/image_service/iiif_manifest.rb +39 -43
  71. data/app/services/geoblacklight_admin/image_service/tms.rb +0 -8
  72. data/app/services/geoblacklight_admin/image_service.rb +1 -1
  73. data/app/services/geoblacklight_admin/item_viewer.rb +4 -4
  74. data/app/views/admin/bookmarks/index.html.erb +19 -14
  75. data/app/views/admin/bulk_actions/show.html.erb +1 -1
  76. data/app/views/admin/document_accesses/import.html.erb +6 -2
  77. data/app/views/admin/document_assets/_assets_table.html.erb +49 -0
  78. data/app/views/admin/document_assets/_form.html.erb +2 -3
  79. data/app/views/admin/document_assets/index.html.erb +1 -47
  80. data/app/views/admin/document_distributions/_document_distribution.html.erb +39 -0
  81. data/app/views/admin/document_distributions/_document_distribution.json.jbuilder +2 -0
  82. data/app/views/admin/document_distributions/_form.html.erb +34 -0
  83. data/app/views/admin/document_distributions/destroy_all.html.erb +82 -0
  84. data/app/views/admin/document_distributions/edit.html.erb +12 -0
  85. data/app/views/admin/document_distributions/import.html.erb +80 -0
  86. data/app/views/admin/document_distributions/index.html.erb +143 -0
  87. data/app/views/admin/document_distributions/index.json.jbuilder +1 -0
  88. data/app/views/admin/document_distributions/new.html.erb +11 -0
  89. data/app/views/admin/document_distributions/show.html.erb +10 -0
  90. data/app/views/admin/document_distributions/show.json.jbuilder +1 -0
  91. data/app/views/admin/documents/_document.html.erb +1 -3
  92. data/app/views/admin/documents/_form.html.erb +2 -4
  93. data/app/views/admin/documents/_form_control.html.erb +5 -2
  94. data/app/views/admin/documents/_form_nav.html.erb +14 -5
  95. data/app/views/admin/documents/_form_nav_kithe.html.erb +4 -1
  96. data/app/views/admin/documents/_json_aardvark.jbuilder +1 -1
  97. data/app/views/admin/documents/_json_gbl_v1.jbuilder +1 -1
  98. data/app/views/admin/documents/_result_selected_options.html.erb +5 -2
  99. data/app/views/admin/documents/admin.html.erb +5 -5
  100. data/app/views/admin/documents/features/_document_references.html.erb +23 -0
  101. data/app/views/admin/documents/features/_multiple_download_links.html.erb +29 -26
  102. data/app/views/admin/ids/fetch.json.jbuilder +0 -2
  103. data/app/views/admin/ids/index.json.jbuilder +0 -2
  104. data/app/views/admin/imports/_form.html.erb +1 -1
  105. data/app/views/admin/imports/show.html.erb +1 -1
  106. data/app/views/admin/layouts/application.html.erb +4 -2
  107. data/app/views/admin/mappings/index.html.erb +1 -1
  108. data/app/views/admin/notifications/_notification.html.haml +29 -28
  109. data/app/views/admin/reference_types/_form.html.erb +25 -0
  110. data/app/views/admin/reference_types/_reference_type.html.erb +52 -0
  111. data/app/views/admin/reference_types/_reference_type.json.jbuilder +2 -0
  112. data/app/views/admin/reference_types/edit.html.erb +12 -0
  113. data/app/views/admin/reference_types/index.html.erb +52 -0
  114. data/app/views/admin/reference_types/index.json.jbuilder +1 -0
  115. data/app/views/admin/reference_types/new.html.erb +11 -0
  116. data/app/views/admin/reference_types/show.html.erb +3 -0
  117. data/app/views/admin/reference_types/show.json.jbuilder +1 -0
  118. data/app/views/admin/shared/_footer.html.erb +5 -2
  119. data/app/views/admin/shared/_js_behaviors.html.erb +2 -3
  120. data/app/views/admin/shared/_navbar.html.erb +9 -2
  121. data/app/views/admin/users/index.html.erb +0 -1
  122. data/app/views/catalog/_show_gbl_admin.html.erb +1 -1
  123. data/config/initializers/defaults.yml +310 -0
  124. data/config/initializers/rails_config.rb +8 -0
  125. data/config/locales/documents.en.yml +14 -0
  126. data/config/routes.rb +30 -5
  127. data/db/import_references_schema_support.numbers +0 -0
  128. data/db/migrate/20230316183001_add_geoblacklight_admin_gem.rb +0 -12
  129. data/db/migrate/20241009200524_create_admin_reference_types.rb +13 -0
  130. data/db/migrate/20241010161420_create_document_references.rb +14 -0
  131. data/db/migrate/20241120238823_rename_references_to_distributions.rb +5 -0
  132. data/db/seeds.rb +5 -0
  133. data/db/seeds_elements.csv +1 -1
  134. data/db/seeds_elements.numbers +0 -0
  135. data/db/seeds_reference_types.csv +29 -0
  136. data/db/seeds_reference_types.numbers +0 -0
  137. data/db/structure.sql +1 -38
  138. data/lib/compose.yml +31 -0
  139. data/lib/generators/geoblacklight_admin/config_generator.rb +53 -12
  140. data/lib/generators/geoblacklight_admin/install_generator.rb +8 -0
  141. data/lib/generators/geoblacklight_admin/templates/btaa_sample_records.csv +5 -0
  142. data/lib/generators/geoblacklight_admin/templates/config/database.yml +1 -1
  143. data/lib/generators/geoblacklight_admin/templates/config/initializers/devise.rb +0 -2
  144. data/lib/generators/geoblacklight_admin/templates/config/initializers/mime_types.rb +1 -0
  145. data/lib/generators/geoblacklight_admin/templates/demo-app/Dockerfile +31 -0
  146. data/lib/generators/geoblacklight_admin/templates/demo-app/compose.yml +42 -0
  147. data/lib/generators/geoblacklight_admin/templates/demo-app/start-server.sh +21 -0
  148. data/lib/geoblacklight_admin/engine.rb +4 -0
  149. data/lib/geoblacklight_admin/rake_task.rb +2 -0
  150. data/lib/geoblacklight_admin/tasks/distributions.rake +69 -0
  151. data/lib/geoblacklight_admin/tasks/images.rake +1 -0
  152. data/lib/geoblacklight_admin/tasks/solr.rake +31 -0
  153. data/lib/geoblacklight_admin/version.rb +1 -1
  154. data/lib/geoblacklight_admin.rb +4 -0
  155. metadata +137 -53
  156. data/app/helpers/import_documents_helper.rb +0 -5
  157. data/app/javascript/entrypoints/engine.js +0 -8
  158. data/config/locales/devise_invitable.en.yml +0 -31
  159. data/lib/generators/geoblacklight_admin/templates/devise/invitations/edit.html.erb +0 -15
  160. data/lib/generators/geoblacklight_admin/templates/devise/invitations/new.html.erb +0 -15
  161. data/lib/generators/geoblacklight_admin/templates/devise/mailer/invitation_instructions.html.erb +0 -11
  162. 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
@@ -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 = Geomg.field_mappings.collect { |key, _value| key }
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
- # jbuilder helper
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
- # qa (questioning_authoriry) gem oddly gives us no route helpers, so
21
- # let's make one ourselves, for it's current mount point, we can change
22
- # it if needed but at least it's DRY.
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
- # From Blacklight::HiddenSearchStateComponent
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.enum_values.document/reference.category").invert.sort.insert(0, ["Choose Reference Type", nil]))).to_s
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
- Element.indexable.each do |elm|
16
- to_field elm.solr_field, obj_extract(elm.index_value)
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
+ });
@@ -0,0 +1,3 @@
1
+ export { default as consumer } from './consumer';
2
+ export { default as exportChannel } from './export_channel';
3
+ export { default as index } from './index';
@@ -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');