geoblacklight_admin 0.9.0 → 0.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d79715a53de267b1c6610d96834bafc9564fa1f1ffd1cc42040ede65c3b3e831
4
- data.tar.gz: 8ffad49338a30230adc65578911502f2d349474b6c1b6e51fb3f41bf7743cf1e
3
+ metadata.gz: 48c3924abd0db3999ab1c702c483d8ba8e57ecee0ce692a7dda60b0707b19b39
4
+ data.tar.gz: be7b643b6306ba2cd44b35e7c32e0161ef9b83b543500dde617535af848bbc1a
5
5
  SHA512:
6
- metadata.gz: 314eb14972a616c59c5c229defdec096ba5c4300520898f636f23f783c62251aec5dd48dea1d0db519a9a442258c11e83b6159422d1e7457ba234a38c9a10189
7
- data.tar.gz: 1f6cd97abecdf5d29e39a7e7088c4db076ceb08e48b49cb0a7fbe0aa0e4a1e4cd37a8a4b42a793f579ca93821ce36da089c48fc923dedbfb2f8dd017ba9d1c3e
6
+ metadata.gz: dedd35ccc8137c52fc6ce2f9d9e99357fb5683689ca3ad484a72bed021b79d09974746fd13ed4eba6594f3b2f655d821f919f29f00e5936e9572363482c63d3a
7
+ data.tar.gz: 4f0557655660b144112a7d532b9f99507f01327bfbba572112ede542bc20f6c0e94ba23f30f692b8ac362c66c6dda3e1027861b743983218c02dc98d47f0a122
@@ -91,24 +91,37 @@ module Admin
91
91
 
92
92
  # DELETE /admin/document_distributions/destroy_all
93
93
  #
94
- # Destroys all document distributions provided in the file parameter. If successful, redirects
95
- # with a success notice. Otherwise, redirects with an error notice.
94
+ # Queues a background job to destroy all document distributions provided in the file parameter.
95
+ # The job will process the CSV file and send a notification when complete.
96
96
  def destroy_all
97
97
  return if request.get?
98
98
 
99
- logger.debug("Destroy Distributions")
99
+ logger.debug("Queue Destroy Distributions Job")
100
100
  unless params.dig(:document_distribution, :distributions, :file)
101
101
  raise ArgumentError, "File does not exist or is invalid."
102
102
  end
103
103
 
104
+ # Save the uploaded file to a temporary location
105
+ uploaded_file = params.dig(:document_distribution, :distributions, :file)
106
+ temp_file_path = Rails.root.join("tmp", "destroy_distributions_#{Time.current.to_i}_#{SecureRandom.hex(8)}.csv")
107
+
108
+ File.binwrite(temp_file_path, uploaded_file.read)
109
+
110
+ # Queue the background job
111
+ DestroyDocumentDistributionsJob.perform_later(temp_file_path.to_s, current_user)
112
+
104
113
  respond_to do |format|
105
- if DocumentDistribution.destroy_all(params.dig(:document_distribution, :distributions, :file))
106
- format.html { redirect_to admin_document_distributions_path, notice: "Distributions were destroyed." }
107
- else
108
- format.html { redirect_to admin_document_distributions_path, notice: "Distributions could not be destroyed." }
109
- end
110
- rescue => e
111
- format.html { redirect_to admin_document_distributions_path, notice: "Distributions could not be destroyed. #{e}" }
114
+ format.html {
115
+ redirect_to admin_document_distributions_path,
116
+ notice: "Distribution destruction job has been queued. You will receive a notification when it completes."
117
+ }
118
+ end
119
+ rescue => e
120
+ respond_to do |format|
121
+ format.html {
122
+ redirect_to admin_document_distributions_path,
123
+ notice: "Failed to queue distribution destruction job: #{e.message}"
124
+ }
112
125
  end
113
126
  end
114
127
 
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ # DestroyDocumentDistributionsJob
6
+ #
7
+ # This job processes a CSV file containing document distribution records to be destroyed.
8
+ # It handles large CSV files in the background to prevent timeouts and provides
9
+ # progress updates via notifications.
10
+ class DestroyDocumentDistributionsJob < ApplicationJob
11
+ queue_as :priority
12
+
13
+ def perform(file_path, current_user)
14
+ logger.debug("DestroyDocumentDistributionsJob: Starting destruction of distributions from #{file_path}")
15
+
16
+ destroyed_count = 0
17
+ error_count = 0
18
+ errors = []
19
+
20
+ begin
21
+ unless File.exist?(file_path)
22
+ raise ArgumentError, "File not found: #{file_path}"
23
+ end
24
+
25
+ CSV.foreach(file_path, headers: true) do |row|
26
+ logger.debug("Processing CSV Row: #{row.to_hash}")
27
+
28
+ begin
29
+ reference_type = ReferenceType.find_by(name: row.to_hash["reference_type"])
30
+
31
+ if reference_type.nil?
32
+ error_count += 1
33
+ errors << "Reference type not found: #{row.to_hash["reference_type"]}"
34
+ next
35
+ end
36
+
37
+ destroyed = DocumentDistribution.destroy_by(
38
+ friendlier_id: row.to_hash["friendlier_id"],
39
+ reference_type_id: reference_type.id,
40
+ url: row.to_hash["distribution_url"]
41
+ )
42
+
43
+ if destroyed.any?
44
+ destroyed_count += destroyed.count
45
+ logger.debug("Destroyed: #{row.to_hash}")
46
+ else
47
+ logger.debug("Not found to destroy: #{row.to_hash}")
48
+ end
49
+ rescue => e
50
+ error_count += 1
51
+ errors << "Error processing row #{row.to_hash}: #{e.message}"
52
+ logger.error("Error destroying distribution: #{e}")
53
+ end
54
+ end
55
+
56
+ # Create success notification
57
+ message = "DISTRIBUTIONS DESTROYED|#{ActionController::Base.helpers.number_with_delimiter(destroyed_count)} distributions destroyed"
58
+ if error_count > 0
59
+ message += " (#{error_count} errors)"
60
+ end
61
+
62
+ notification = ExportNotification.with(message: message)
63
+ notification.deliver(current_user)
64
+
65
+ # Clean up the temporary file
66
+ File.delete(file_path) if File.exist?(file_path)
67
+
68
+ logger.debug("DestroyDocumentDistributionsJob: Completed. Destroyed #{destroyed_count} distributions with #{error_count} errors")
69
+ rescue => e
70
+ logger.error("DestroyDocumentDistributionsJob: Fatal error - #{e}")
71
+
72
+ # Create error notification
73
+ notification = ExportNotification.with(message: "DISTRIBUTION DESTROY FAILED|Error: #{e.message}")
74
+ notification.deliver(current_user)
75
+
76
+ # Clean up the temporary file
77
+ File.delete(file_path) if File.exist?(file_path)
78
+ end
79
+ end
80
+ end
@@ -18,6 +18,9 @@
18
18
  <p class="alert alert-danger" role="alert">
19
19
  <strong>Warning:</strong> All matching Distributions will be destroyed. There is <strong>NO UNDO</strong> here.
20
20
  </p>
21
+ <p class="alert alert-info" role="alert">
22
+ <strong>Note:</strong> Large CSV files will be processed in the background. You will receive a notification when the process completes.
23
+ </p>
21
24
  <h3 class='h4'>Upload a CSV File</h3>
22
25
 
23
26
  <%= simple_form_for DocumentDistribution.new, url: destroy_all_admin_document_distributions_path, method: :post, multipart: true do |f| %>
@@ -193,7 +193,7 @@
193
193
  </tr>
194
194
  </thead>
195
195
  <tbody>
196
- <% @document.document_accesses.each do |da| %>
196
+ <% @document.document_licensed_accesses.each do |da| %>
197
197
  <tr>
198
198
  <td><%= da.institution_code %></td>
199
199
  <td><a href="<%= da.access_url %>"><%= da.access_url %></a></td>
@@ -1,7 +1,7 @@
1
- <%- @page_title = "GBL♦Admin - Exports" %>
1
+ <%- @page_title = "GBL♦Admin - Notifications" %>
2
2
 
3
3
  <h1 style="width:100%;">
4
- <%= t('dictionary.exports') %>
4
+ <%= t('dictionary.notifications') %>
5
5
 
6
6
  <%= link_to('+ Mark All Read', batch_admin_notifications_path(params: {read: 'all'}), {method: 'put', class: "btn btn-primary float-right mr-2"}) %>
7
7
  </h1>
@@ -35,7 +35,7 @@
35
35
  <% if user_signed_in? %>
36
36
  <li class="nav-item">
37
37
  <%= link_to admin_notifications_url, { class: 'nav-link' } do %>
38
- <%= "Exports #{notifications_badge}".html_safe %>
38
+ <%= "Notifications #{notifications_badge}".html_safe %>
39
39
  <% end %>
40
40
  </li>
41
41
  <% end %>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GeoblacklightAdmin
4
- VERSION = "0.9.0"
4
+ VERSION = "0.10.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoblacklight_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Larson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-26 00:00:00.000000000 Z
11
+ date: 2025-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_storage_validations
@@ -458,6 +458,20 @@ dependencies:
458
458
  - - "~>"
459
459
  - !ruby/object:Gem::Version
460
460
  version: '2.6'
461
+ - !ruby/object:Gem::Dependency
462
+ name: rubyzip
463
+ requirement: !ruby/object:Gem::Requirement
464
+ requirements:
465
+ - - "~>"
466
+ - !ruby/object:Gem::Version
467
+ version: '2.3'
468
+ type: :runtime
469
+ prerelease: false
470
+ version_requirements: !ruby/object:Gem::Requirement
471
+ requirements:
472
+ - - "~>"
473
+ - !ruby/object:Gem::Version
474
+ version: '2.3'
461
475
  - !ruby/object:Gem::Dependency
462
476
  name: byebug
463
477
  requirement: !ruby/object:Gem::Requirement
@@ -855,6 +869,7 @@ files:
855
869
  - app/jobs/bulk_action_revert_job.rb
856
870
  - app/jobs/bulk_action_run_document_job.rb
857
871
  - app/jobs/bulk_action_run_job.rb
872
+ - app/jobs/destroy_document_distributions_job.rb
858
873
  - app/jobs/export_job.rb
859
874
  - app/jobs/export_json_bulk_job.rb
860
875
  - app/jobs/export_json_job.rb