geoblacklight_admin 0.5.1 → 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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -9
  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 +1 -1
  10. data/app/controllers/admin/assets_controller.rb +41 -5
  11. data/app/controllers/admin/bookmarks_controller.rb +14 -2
  12. data/app/controllers/admin/bulk_actions_controller.rb +31 -0
  13. data/app/controllers/admin/document_accesses_controller.rb +38 -0
  14. data/app/controllers/admin/document_assets_controller.rb +46 -9
  15. data/app/controllers/admin/document_distributions_controller.rb +172 -0
  16. data/app/controllers/admin/documents_controller.rb +41 -55
  17. data/app/controllers/admin/elements_controller.rb +22 -0
  18. data/app/controllers/admin/form_elements_controller.rb +31 -0
  19. data/app/controllers/admin/import_documents_controller.rb +11 -1
  20. data/app/controllers/admin/imports_controller.rb +32 -2
  21. data/app/controllers/admin/mappings_controller.rb +15 -0
  22. data/app/controllers/admin/notifications_controller.rb +27 -0
  23. data/app/controllers/admin/reference_types_controller.rb +106 -0
  24. data/app/controllers/admin/search_controller.rb +7 -0
  25. data/app/controllers/admin/users_controller.rb +10 -0
  26. data/app/helpers/asset_helper.rb +6 -0
  27. data/app/helpers/bulk_actions_helper.rb +9 -0
  28. data/app/helpers/document_helper.rb +36 -0
  29. data/app/helpers/geoblacklight_admin_helper.rb +88 -8
  30. data/app/helpers/mappings_helper.rb +26 -0
  31. data/app/indexers/document_indexer.rb +22 -2
  32. data/app/javascript/channels/consumer.js +6 -0
  33. data/app/javascript/channels/export_channel.js +30 -0
  34. data/app/javascript/channels/index.js +3 -0
  35. data/app/javascript/controllers/results_controller.js +14 -0
  36. data/app/javascript/index.js +8 -2
  37. data/app/jobs/export_job.rb +35 -8
  38. data/app/jobs/geoblacklight_admin/delete_thumbnail_job.rb +19 -0
  39. data/app/jobs/geoblacklight_admin/remove_parent_dct_references_uri_job.rb +16 -0
  40. data/app/jobs/geoblacklight_admin/set_parent_dct_references_uri_job.rb +17 -0
  41. data/app/jobs/geoblacklight_admin/store_image_job.rb +22 -0
  42. data/app/models/asset.rb +20 -0
  43. data/app/models/bulk_action.rb +2 -1
  44. data/app/models/document/geom_validator.rb +8 -0
  45. data/app/models/document/reference.rb +65 -65
  46. data/app/models/document.rb +128 -71
  47. data/app/models/document_distribution.rb +145 -0
  48. data/app/models/element.rb +2 -0
  49. data/app/models/geoblacklight_admin/schema.rb +10 -2
  50. data/app/models/import_document_state_machine.rb +1 -0
  51. data/app/models/reference_type.rb +40 -0
  52. data/app/models/user.rb +4 -2
  53. data/app/services/export_csv_document_distributions_service.rb +61 -0
  54. data/app/services/geoblacklight_admin/image_service/tms.rb +0 -4
  55. data/app/services/geoblacklight_admin/image_service.rb +1 -1
  56. data/app/services/geoblacklight_admin/item_viewer.rb +4 -4
  57. data/app/views/admin/bulk_actions/show.html.erb +1 -1
  58. data/app/views/admin/document_accesses/import.html.erb +6 -2
  59. data/app/views/admin/document_assets/_assets_table.html.erb +49 -0
  60. data/app/views/admin/document_assets/_form.html.erb +2 -3
  61. data/app/views/admin/document_assets/index.html.erb +1 -47
  62. data/app/views/admin/document_distributions/_document_distribution.html.erb +39 -0
  63. data/app/views/admin/document_distributions/_document_distribution.json.jbuilder +2 -0
  64. data/app/views/admin/document_distributions/_form.html.erb +34 -0
  65. data/app/views/admin/document_distributions/destroy_all.html.erb +82 -0
  66. data/app/views/admin/document_distributions/edit.html.erb +12 -0
  67. data/app/views/admin/document_distributions/import.html.erb +80 -0
  68. data/app/views/admin/document_distributions/index.html.erb +143 -0
  69. data/app/views/admin/document_distributions/index.json.jbuilder +1 -0
  70. data/app/views/admin/document_distributions/new.html.erb +11 -0
  71. data/app/views/admin/document_distributions/show.html.erb +10 -0
  72. data/app/views/admin/document_distributions/show.json.jbuilder +1 -0
  73. data/app/views/admin/documents/_document.html.erb +1 -3
  74. data/app/views/admin/documents/_form.html.erb +2 -4
  75. data/app/views/admin/documents/_form_control.html.erb +5 -2
  76. data/app/views/admin/documents/_form_nav.html.erb +14 -5
  77. data/app/views/admin/documents/_form_nav_kithe.html.erb +4 -1
  78. data/app/views/admin/documents/_json_aardvark.jbuilder +1 -1
  79. data/app/views/admin/documents/_json_gbl_v1.jbuilder +1 -1
  80. data/app/views/admin/documents/_result_selected_options.html.erb +5 -2
  81. data/app/views/admin/documents/admin.html.erb +5 -5
  82. data/app/views/admin/documents/features/_document_references.html.erb +23 -0
  83. data/app/views/admin/documents/features/_multiple_download_links.html.erb +29 -26
  84. data/app/views/admin/ids/fetch.json.jbuilder +0 -2
  85. data/app/views/admin/ids/index.json.jbuilder +0 -2
  86. data/app/views/admin/imports/_form.html.erb +1 -1
  87. data/app/views/admin/imports/show.html.erb +1 -1
  88. data/app/views/admin/layouts/application.html.erb +4 -2
  89. data/app/views/admin/reference_types/_form.html.erb +25 -0
  90. data/app/views/admin/reference_types/_reference_type.html.erb +52 -0
  91. data/app/views/admin/reference_types/_reference_type.json.jbuilder +2 -0
  92. data/app/views/admin/reference_types/edit.html.erb +12 -0
  93. data/app/views/admin/reference_types/index.html.erb +52 -0
  94. data/app/views/admin/reference_types/index.json.jbuilder +1 -0
  95. data/app/views/admin/reference_types/new.html.erb +11 -0
  96. data/app/views/admin/reference_types/show.html.erb +3 -0
  97. data/app/views/admin/reference_types/show.json.jbuilder +1 -0
  98. data/app/views/admin/shared/_footer.html.erb +5 -2
  99. data/app/views/admin/shared/_js_behaviors.html.erb +2 -3
  100. data/app/views/admin/shared/_navbar.html.erb +9 -2
  101. data/app/views/admin/users/index.html.erb +0 -1
  102. data/app/views/catalog/_show_gbl_admin.html.erb +1 -1
  103. data/config/initializers/defaults.yml +310 -0
  104. data/config/initializers/rails_config.rb +8 -0
  105. data/config/locales/documents.en.yml +14 -0
  106. data/config/routes.rb +30 -5
  107. data/db/import_references_schema_support.numbers +0 -0
  108. data/db/migrate/20230316183001_add_geoblacklight_admin_gem.rb +0 -12
  109. data/db/migrate/20241009200524_create_admin_reference_types.rb +13 -0
  110. data/db/migrate/20241010161420_create_document_references.rb +14 -0
  111. data/db/migrate/20241120238823_rename_references_to_distributions.rb +5 -0
  112. data/db/seeds.rb +5 -0
  113. data/db/seeds_elements.csv +1 -1
  114. data/db/seeds_elements.numbers +0 -0
  115. data/db/seeds_reference_types.csv +29 -0
  116. data/db/seeds_reference_types.numbers +0 -0
  117. data/db/structure.sql +1 -38
  118. data/lib/compose.yml +31 -0
  119. data/lib/generators/geoblacklight_admin/config_generator.rb +48 -12
  120. data/lib/generators/geoblacklight_admin/install_generator.rb +8 -0
  121. data/lib/generators/geoblacklight_admin/templates/config/database.yml +1 -1
  122. data/lib/generators/geoblacklight_admin/templates/config/initializers/devise.rb +0 -2
  123. data/lib/generators/geoblacklight_admin/templates/config/initializers/mime_types.rb +1 -0
  124. data/lib/generators/geoblacklight_admin/templates/demo-app/Dockerfile +31 -0
  125. data/lib/generators/geoblacklight_admin/templates/demo-app/compose.yml +42 -0
  126. data/lib/generators/geoblacklight_admin/templates/demo-app/start-server.sh +21 -0
  127. data/lib/geoblacklight_admin/engine.rb +4 -0
  128. data/lib/geoblacklight_admin/tasks/distributions.rake +69 -0
  129. data/lib/geoblacklight_admin/tasks/images.rake +1 -0
  130. data/lib/geoblacklight_admin/tasks/solr.rake +31 -0
  131. data/lib/geoblacklight_admin/version.rb +1 -1
  132. data/lib/geoblacklight_admin.rb +4 -0
  133. metadata +78 -41
  134. data/app/javascript/entrypoints/engine.js +0 -8
  135. data/config/locales/devise_invitable.en.yml +0 -31
  136. data/lib/generators/geoblacklight_admin/templates/devise/invitations/edit.html.erb +0 -15
  137. data/lib/generators/geoblacklight_admin/templates/devise/invitations/new.html.erb +0 -15
  138. data/lib/generators/geoblacklight_admin/templates/devise/mailer/invitation_instructions.html.erb +0 -11
  139. data/lib/generators/geoblacklight_admin/templates/devise/mailer/invitation_instructions.text.erb +0 -11
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ # DocumentDistribution
6
+ #
7
+ # This class represents a distribution of a document, which includes a URL and a distribution type.
8
+ # It belongs to a document and a reference type, and it supports CSV import and export.
9
+ #
10
+ # Associations:
11
+ # - belongs_to :document
12
+ # - belongs_to :reference_type
13
+ #
14
+ # Callbacks:
15
+ # - after_save :reindex_document
16
+ #
17
+ # Validations:
18
+ # - Validates presence of :friendlier_id, :reference_type_id, :url
19
+ # - Validates uniqueness of :url scoped to :friendlier_id and :reference_type_id
20
+ #
21
+ # Scopes:
22
+ # - to_aardvark_distributions: Converts distributions to aardvark format
23
+ # - to_csv: Converts distributions to CSV format
24
+ class DocumentDistribution < ApplicationRecord
25
+ belongs_to :document, foreign_key: :friendlier_id, primary_key: :friendlier_id
26
+ belongs_to :reference_type
27
+ after_save :reindex_document
28
+
29
+ # Validations
30
+ validates :friendlier_id, :reference_type_id, :url, presence: true
31
+ validates :url, uniqueness: {scope: [:friendlier_id, :reference_type_id]}
32
+
33
+ # Scopes
34
+ scope :to_aardvark_distributions, -> {
35
+ distributions = where(friendlier_id: pluck(:friendlier_id)).map(&:to_aardvark_distribution)
36
+ merged = {}
37
+ distributions.each do |dist|
38
+ if dist.keys.first == "http://schema.org/downloadUrl"
39
+ merged["http://schema.org/downloadUrl"] ||= []
40
+ merged["http://schema.org/downloadUrl"] << {
41
+ "url" => dist.values.first,
42
+ "label" => dist[:label]
43
+ }
44
+ else
45
+ merged[dist.keys.first] = dist.values.first
46
+ end
47
+ end
48
+ merged
49
+ }
50
+ scope :to_csv, -> { where(friendlier_id: pluck(:friendlier_id)).map(&:to_csv) }
51
+
52
+ # CSV Column Names
53
+ #
54
+ # Returns an array of column names for CSV export.
55
+ #
56
+ # @return [Array<String>] the CSV column names
57
+ def self.csv_column_names
58
+ ["friendlier_id", "reference_type", "distribution_url", "label"]
59
+ end
60
+
61
+ # Import
62
+ #
63
+ # Imports document distributions from a CSV file.
64
+ #
65
+ # @param file [File] the CSV file to import
66
+ # @return [Boolean] true if import is successful
67
+ def self.import(file)
68
+ logger.debug("CSV Import")
69
+ ::CSV.foreach(file.path, headers: true) do |row|
70
+ logger.debug("CSV Row: #{row.to_hash}")
71
+ document_distribution = DocumentDistribution.find_or_initialize_by(
72
+ friendlier_id: row.to_hash["friendlier_id"],
73
+ reference_type_id: ReferenceType.find_by(name: row.to_hash["reference_type"]).id,
74
+ url: row.to_hash["distribution_url"],
75
+ label: row.to_hash["label"]
76
+ )
77
+
78
+ logger.debug("Document Distribution: #{document_distribution.inspect}")
79
+
80
+ document_distribution.update!(
81
+ friendlier_id: row.to_hash["friendlier_id"],
82
+ reference_type_id: ReferenceType.find_by(name: row.to_hash["reference_type"]).id,
83
+ url: row.to_hash["distribution_url"],
84
+ label: row.to_hash["label"]
85
+ )
86
+ end
87
+ true
88
+ end
89
+
90
+ # Destroy All
91
+ #
92
+ # Destroys document distributions based on a CSV file.
93
+ #
94
+ # @param file [File] the CSV file to process
95
+ # @return [Boolean] true if destroy is successful
96
+ def self.destroy_all(file)
97
+ logger.debug("CSV Destroy")
98
+ ::CSV.foreach(file.path, headers: true) do |row|
99
+ logger.debug("CSV Row: #{row.to_hash}")
100
+ if DocumentDistribution.destroy_by(
101
+ friendlier_id: row.to_hash["friendlier_id"],
102
+ reference_type_id: ReferenceType.find_by(name: row.to_hash["reference_type"]).id,
103
+ url: row.to_hash["distribution_url"]
104
+ )
105
+ logger.debug("Destroyed: #{row.to_hash}")
106
+ else
107
+ logger.debug("Not Destroyed: #{row.to_hash}")
108
+ end
109
+ end
110
+ true
111
+ end
112
+
113
+ # To CSV
114
+ #
115
+ # Converts the document distribution to an array suitable for CSV export.
116
+ #
117
+ # @return [Array<String>] the CSV row data
118
+ def to_csv
119
+ [
120
+ friendlier_id,
121
+ reference_type.name,
122
+ url,
123
+ label
124
+ ]
125
+ end
126
+
127
+ # To Aardvark Reference
128
+ #
129
+ # Converts the document distribution to an aardvark distribution format.
130
+ #
131
+ # @return [Hash] the aardvark reference
132
+ def to_aardvark_distribution
133
+ hash = {}
134
+ hash[reference_type.reference_uri.to_s] = url
135
+ hash[:label] = label if reference_type.reference_uri.to_s == "http://schema.org/downloadUrl"
136
+ hash
137
+ end
138
+
139
+ # Reindex Document
140
+ #
141
+ # Reindexes the associated document.
142
+ def reindex_document
143
+ document.save
144
+ end
145
+ end
@@ -22,6 +22,8 @@ class Element < ApplicationRecord
22
22
 
23
23
  # Validations
24
24
  validates :label, :solr_field, :field_type, presence: true
25
+ validates :label, uniqueness: true
26
+ validates :solr_field, uniqueness: true
25
27
 
26
28
  FIELD_TYPES = %w[
27
29
  string
@@ -31,7 +31,11 @@ module GeoblacklightAdmin
31
31
  }
32
32
  end
33
33
 
34
- @fields = @fields.merge(dct_references_import_mappings)
34
+ unless ENV["GBL_ADMIN_REFERENCES_MIGRATED"] == "true"
35
+ Rails.logger.warn("Deprecation warning: AttrJSON-based dct_references_s will not be supported soon.")
36
+ @fields = @fields.merge(dct_references_import_mappings)
37
+ end
38
+
35
39
  @fields
36
40
  end
37
41
 
@@ -63,7 +67,11 @@ module GeoblacklightAdmin
63
67
  }
64
68
  }
65
69
 
66
- @fields = @fields.merge(dct_references_import_mappings)
70
+ unless ENV["GBL_ADMIN_REFERENCES_MIGRATED"] == "true"
71
+ Rails.logger.warn("Deprecation warning: AttrJSON-based dct_references_s will not be supported soon.")
72
+ @fields = @fields.merge(dct_references_import_mappings)
73
+ end
74
+
67
75
  @fields = @fields.merge(object_metadata)
68
76
  @fields
69
77
  end
@@ -9,4 +9,5 @@ class ImportDocumentStateMachine
9
9
  state :failed
10
10
 
11
11
  transition from: :queued, to: %i[success failed]
12
+ transition from: :failed, to: :success
12
13
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The ReferenceType class represents a reference entity in the application.
4
+ # It includes validations for presence and uniqueness of reference attributes,
5
+ # and manages the position of references within the system.
6
+ class ReferenceType < ApplicationRecord
7
+ has_many :document_distributions, dependent: :destroy
8
+
9
+ # Validations
10
+ # Ensures that both reference_type and reference_uri are present and unique.
11
+ validates :name, :reference_type, :reference_uri, presence: true
12
+ validates :name, :reference_type, uniqueness: true
13
+
14
+ # Callbacks
15
+ # Sets the position of the reference before it is created.
16
+ before_create :set_last_position
17
+
18
+ # Sets the position of the reference to the next available position.
19
+ # If no references exist, it sets the position to 1.
20
+ #
21
+ # @return [void]
22
+ def set_last_position
23
+ position = ReferenceType.all.order(position: :desc)&.first&.position
24
+ self.position = position.blank? ? 1 : position + 1
25
+ end
26
+
27
+ # Class method to sort elements based on an array of IDs.
28
+ # Updates the position of each ReferenceType according to the order in the array.
29
+ #
30
+ # @param id_array [Array<Integer>] An array of element IDs to be sorted.
31
+ # @return [void]
32
+ def self.sort_elements(id_array)
33
+ transaction do
34
+ logger.debug { id_array.inspect }
35
+ id_array.each_with_index do |elm_id, i|
36
+ ReferenceType.update(elm_id, position: i)
37
+ end
38
+ end
39
+ end
40
+ end
data/app/models/user.rb CHANGED
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "devise"
4
+
3
5
  # User
4
6
  class User < ApplicationRecord
7
+ extend Devise::Models
5
8
  include Blacklight::User
6
9
 
7
10
  # Include default devise modules. Others available are:
8
11
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
9
- devise :invitable, :database_authenticatable,
10
- :recoverable, :rememberable, :validatable
12
+ devise :database_authenticatable, :recoverable, :rememberable, :validatable
11
13
 
12
14
  has_many :bookmarks, dependent: :destroy, as: :user
13
15
  has_many :notifications, dependent: :destroy, as: :recipient
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ # ExportCsvDocumentDistributionsService
6
+ #
7
+ # This service is responsible for exporting document distributions to a CSV format.
8
+ # It broadcasts the progress of the export process via ActionCable.
9
+ class ExportCsvDocumentDistributionsService
10
+ # Returns a short name for the service.
11
+ #
12
+ # @return [String] the short name of the service.
13
+ def self.short_name
14
+ "Document Distributions"
15
+ end
16
+
17
+ # Initiates the CSV export process for the given document IDs.
18
+ #
19
+ # @param document_ids [Array] an array of document IDs to export.
20
+ # @return [Array] the generated CSV file content as an array of rows.
21
+ #
22
+ # This method broadcasts the progress of the export process to the "export_channel".
23
+ # It processes the document IDs in slices and handles any NoMethodError exceptions
24
+ # that occur during the export process.
25
+ def self.call(document_ids)
26
+ ActionCable.server.broadcast("export_channel", {progress: 0})
27
+
28
+ document_ids = document_ids.flatten
29
+ total = document_ids.size
30
+ count = 0
31
+ slice_count = 100
32
+ csv_file = []
33
+
34
+ Rails.logger.debug { "\n\nExportCsvDocumentDistributionsService: #{document_ids.inspect}\n\n" }
35
+
36
+ CSV.generate(headers: true) do |_csv|
37
+ csv_file << DocumentDistribution.csv_column_names
38
+ document_ids.each_slice(slice_count) do |slice|
39
+ # Broadcast progress percentage
40
+ count += slice_count
41
+ progress = ((count.to_f / total) * 100).round
42
+ progress = 100 if progress > 100
43
+
44
+ ActionCable.server.broadcast("export_channel", {progress: progress})
45
+ slice.each do |doc_id|
46
+ doc = Document.find_by(friendlier_id: doc_id)
47
+
48
+ Rails.logger.debug { "\n\nDocDistributions: #{doc.document_distributions.size}\n\n" }
49
+
50
+ doc.document_distributions.each do |distribution|
51
+ csv_file << distribution.to_csv
52
+ end
53
+ rescue NoMethodError
54
+ Rails.logger.debug { "\n\nExport Failed: #{doc_id.inspect}\n\n" }
55
+ end
56
+ end
57
+ end
58
+
59
+ csv_file
60
+ end
61
+ end
@@ -23,16 +23,12 @@ module GeoblacklightAdmin
23
23
  # Parse the URL using Addressable::URI which handles more complex URIs
24
24
  parsed_url = Addressable::URI.parse(document.viewer_endpoint)
25
25
 
26
- puts "Parsed URL: #{parsed_url.inspect}"
27
-
28
26
  # Build a hash to store the extracted components
29
27
  parsed_data = {
30
28
  base_url: "#{parsed_url.scheme}://#{parsed_url.host}#{parsed_url.port ? ":" + parsed_url.port.to_s : ""}",
31
29
  path_pattern: parsed_url.path
32
30
  }
33
31
 
34
- puts "Parsed Data: #{parsed_data.inspect}"
35
-
36
32
  endpoint = parsed_data[:base_url]
37
33
  "#{endpoint}/geoserver/wms/reflect?" \
38
34
  "&FORMAT=image%2Fpng" \
@@ -191,7 +191,7 @@ module GeoblacklightAdmin
191
191
 
192
192
  # Retreives a url to a static thumbnail from the document's dct_references field, if it exists.
193
193
  def image_reference
194
- @document.references["http://schema.org/thumbnailUrl"]
194
+ @document.distributions["http://schema.org/thumbnailUrl"]
195
195
  end
196
196
 
197
197
  # Default image size.
@@ -2,9 +2,9 @@
2
2
 
3
3
  module GeoblacklightAdmin
4
4
  class ItemViewer
5
- def initialize(references)
6
- @references = references
7
- @keys = references.keys.collect { |k| reference_uri_2_key(k) }
5
+ def initialize(distributions)
6
+ @distributions = distributions
7
+ @keys = distributions.keys.collect { |k| reference_uri_2_key(k) }
8
8
  end
9
9
 
10
10
  def viewer_protocol
@@ -12,7 +12,7 @@ module GeoblacklightAdmin
12
12
  end
13
13
 
14
14
  def viewer_endpoint
15
- @references[viewer_protocol_2_endpoint]
15
+ @distributions[viewer_protocol_2_endpoint]
16
16
  end
17
17
 
18
18
  def reference_uri_2_key(value)
@@ -43,7 +43,7 @@
43
43
  <% if @bulk_action.state_machine.current_state == 'created' %>
44
44
  <%= form_tag run_admin_bulk_action_path(@bulk_action), method: :patch do -%>
45
45
  <%= hidden_field_tag :run, true -%>
46
- <%= submit_tag 'Run Bulk Action' -%>
46
+ <%= submit_tag '+ Run Bulk Action', class: 'btn btn-primary btn-block' -%>
47
47
  <%- end -%>
48
48
  <% else %>
49
49
  <%= @bulk_action.state_machine.current_state %>
@@ -15,7 +15,11 @@
15
15
  <h2 class='h3'>Import for Multiple Documents</h2>
16
16
  <% end %>
17
17
 
18
- <h3 class='h4'>Import a CSV File</h3>
18
+ <p class="alert alert-info" role="alert">
19
+ <strong>Note:</strong> New Institutional Access URLs will be created. Existing Institutional Access URLs will be updated per the CSV file.
20
+ </p>
21
+
22
+ <h3 class='h4'>Upload a CSV File</h3>
19
23
  <%= simple_form_for DocumentAccess.new, url: import_admin_document_accesses_path, method: :post, multipart: true do |f| %>
20
24
  <div class="form-inputs">
21
25
  <%= f.simple_fields_for :assets do |asset_fields| %>
@@ -24,7 +28,7 @@
24
28
  </div>
25
29
 
26
30
  <div class="form-actions">
27
- <%= submit_tag "Import CSV", {class: 'btn btn-primary'} %>
31
+ <%= submit_tag "+ Import CSV", {class: 'btn btn-primary'} %>
28
32
  </div>
29
33
  <% end %>
30
34
  </div>
@@ -0,0 +1,49 @@
1
+ <div class="table-responsive">
2
+ <table class="table table-striped table-bordered sortable">
3
+ <thead class="thead-dark">
4
+ <tr>
5
+ <th>Thumbnail</th>
6
+ <th>Preview</th>
7
+ <th>Title</th>
8
+ <th>Label</th>
9
+ <th>MimeType</th>
10
+ <th>Reference URI Type</th>
11
+ <th colspan="2">Actions</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <% document_assets.each do |document_asset| %>
16
+ <tr>
17
+ <td>
18
+ <%= form_with model: document_asset, url: admin_document_document_asset_path(document_asset.parent, document_asset), method: :put, remote: true, class: 'thumbnail-form' do |f| %>
19
+ <%= f.check_box :thumbnail, class: 'thumbnail-toggle', onchange: "this.form.submit()" %>
20
+ <%= f.submit 'Save', class: 'btn btn-sm btn-primary d-none' %>
21
+ <% end %>
22
+ </td>
23
+ <td>
24
+ <% if document_asset.respond_to?(:thumbnail) %>
25
+ <% unless document_asset.file_url(:thumb_standard).nil? %>
26
+ <%= image_tag(document_asset.file_url(:thumb_standard), { height: 100 }) %>
27
+ <% end %>
28
+ <% end %>
29
+ </td>
30
+ <td><%= link_to(document_asset.title, document_asset.file.url) %></td>
31
+ <td><%= document_asset.label %></td>
32
+ <td>
33
+ <%= document_asset.file_data["metadata"]["mime_type"] %>
34
+ <span class="sr-only"><%= document_asset.inspect %></span>
35
+ </td>
36
+ <td>
37
+ <%= document_asset.dct_references_uri_key %>
38
+ </td>
39
+ <td>
40
+ <%= link_to 'Edit', edit_admin_document_document_asset_path(document_asset.parent, document_asset) %>
41
+ </td>
42
+ <td>
43
+ <%= link_to 'Destroy', admin_document_document_asset_path(document_asset.parent, document_asset), method: :delete, data: { confirm: 'Are you sure?' } %>
44
+ </td>
45
+ </tr>
46
+ <% end %>
47
+ </tbody>
48
+ </table>
49
+ </div>
@@ -1,11 +1,10 @@
1
- <%= @document_asset.class %>
2
-
3
1
  <%= simple_form_for [:admin, @document, @document_asset], :url => admin_document_document_asset_path(@document, @document_asset) do |f| %>
4
2
  <%= f.error_notification %>
5
3
  <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
6
4
 
7
5
  <div class="form-inputs">
8
- <%= f.input :parent_id, input_html: { value: @document.friendlier_id, readonly: true } %>
6
+ <%= link_to "Parent Document", admin_document_path(@document_asset.parent) %>
7
+ <%= f.input :parent_id, as: :hidden %>
9
8
  <%= f.input :title %>
10
9
  <%= f.input :label %>
11
10
  <%= f.input :dct_references_uri_key, collection: I18n.t("activemodel.enum_values.document/reference.category").invert.sort.insert(0, ["Choose Reference Type", nil]), label: 'Reference' %>
@@ -30,53 +30,7 @@
30
30
  </h6>
31
31
  <% end %>
32
32
 
33
- <div class="table-responsive">
34
- <table class="table table-striped table-bordered sortable">
35
- <thead class="thead-dark">
36
- <tr>
37
- <th>Thumbnail</th>
38
- <th>Preview</th>
39
- <th>Title</th>
40
- <th>Label</th>
41
- <th>MimeType</th>
42
- <th>Reference URI Type</th>
43
- <th colspan="2">Actions</th>
44
- </tr>
45
- </thead>
46
- <tbody>
47
- <% @document_assets.each do |document_asset| %>
48
- <tr>
49
- <td>
50
- <% if document_asset.respond_to?(:thumbnail) %>
51
- <%= document_asset.thumbnail %>
52
- <% end %>
53
- </td>
54
- <td>
55
- <% if document_asset.respond_to?(:thumbnail) %>
56
- <% unless document_asset.file_url(:thumb_standard).nil? %>
57
- <%= image_tag(document_asset.file_url(:thumb_standard), { height: 100 }) %>
58
- <% end %>
59
- <% end %>
60
- </td>
61
- <td><%= link_to(document_asset.title, document_asset.file.url) %></td>
62
- <td><%= document_asset.label %></td>
63
- <td>
64
- <%= document_asset.file_data["metadata"]["mime_type"] %>
65
- <span class="sr-only"><%= document_asset.inspect %></span>
66
- </td>
67
- <td>
68
- <%= document_asset.dct_references_uri_key %>
69
- </td>
70
- <td>
71
- <%= link_to 'Edit', edit_admin_document_document_asset_path(document_asset.parent, document_asset) %>
72
- </td>
73
- <td>
74
- <%= link_to 'Destroy', admin_document_document_asset_path(document_asset.parent, document_asset), method: :delete, data: { confirm: 'Are you sure?' } %>
75
- </td>
76
- </tr>
77
- <% end %>
78
- </tbody>
79
- </table>
33
+ <%= render partial: 'assets_table', locals: { document_assets: @document_assets } %>
80
34
 
81
35
  <% if @pagy %>
82
36
  <h6>
@@ -0,0 +1,39 @@
1
+ <%- @page_title = "GBL♦Admin - Document - Distribution - #{document_distribution.url}" %>
2
+
3
+ <h1>Distribution</h1>
4
+
5
+ <div class="row">
6
+ <div class="col-9">
7
+ <h2>
8
+ <%= document_distribution.url %>
9
+ <span class="float-right">
10
+ <%= link_to '~ Edit Distribution', edit_admin_document_document_distribution_path(@document, document_distribution), { class: 'btn btn-primary' } %>
11
+ <%= button_to "Destroy this distribution", admin_document_document_distribution_path(@document, document_distribution), method: :delete, class: "btn btn-danger" %>
12
+ </span>
13
+ </h2>
14
+
15
+ <table class="table table-bordered">
16
+ <thead class="thead-dark">
17
+ <tr>
18
+ <th class="header" style="width:300px;">Attribute</th>
19
+ <th class="header">Value</th>
20
+ </tr>
21
+ </thead>
22
+ <tr>
23
+ <th>Reference Type</th>
24
+ <td><%= document_distribution.reference_type.reference_type %></td>
25
+ </tr>
26
+ <tr>
27
+ <th>Reference URL</th>
28
+ <td><%= document_distribution.url %></td>
29
+ </tr>
30
+ <tr>
31
+ <th>Label</th>
32
+ <td><%= document_distribution.label %></td>
33
+ </tr>
34
+ </table>
35
+ </div>
36
+ </div>
37
+
38
+ <%= link_to 'Edit', edit_admin_document_document_distribution_path(@document, document_distribution) %> |
39
+ <%= link_to 'Back', admin_document_document_distributions_path(@document) %>
@@ -0,0 +1,2 @@
1
+ json.extract! document_distribution, :id, :created_at, :updated_at
2
+ json.url document_distribution_url(document_distribution, format: :json)
@@ -0,0 +1,34 @@
1
+ <%= simple_form_for([:admin, @document, @document_distribution]) do |f| %>
2
+ <%= f.error_notification %>
3
+ <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
4
+
5
+ <div class="form-inputs">
6
+ <%= f.input :friendlier_id, input_html: { value: @document.friendlier_id, readonly: true } %>
7
+ <%= f.input :reference_type_id, as: :select, collection: ReferenceType.all.map { |r| [r.reference_type, r.id] }, label: 'Reference Type' %>
8
+ <%= f.input :url, label: 'Distribution URL' %>
9
+ <%= f.input :label, autofocus: true, input_html: { disabled: true, id: 'label-input' } %>
10
+
11
+ </div>
12
+
13
+ <div class="form-actions">
14
+ <%= f.button :submit, 'Create Download URL', {class: 'btn btn-primary'} %>
15
+ </div>
16
+ <% end %>
17
+
18
+ <script>
19
+ document.addEventListener('DOMContentLoaded', function() {
20
+ const distributionSelect = document.querySelector('select[name="document_distribution[reference_type_id]"]');
21
+ const labelInput = document.getElementById('label-input');
22
+
23
+ function toggleLabelInput() {
24
+ if (distributionSelect.options[distributionSelect.selectedIndex].text === 'Download file') {
25
+ labelInput.disabled = false;
26
+ } else {
27
+ labelInput.disabled = true;
28
+ }
29
+ }
30
+
31
+ distributionSelect.addEventListener('change', toggleLabelInput);
32
+ toggleLabelInput(); // Initial check
33
+ });
34
+ </script>