geoblacklight_admin 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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>