geoblacklight_admin 0.6.3 → 0.7.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/app/assets/stylesheets/geoblacklight_admin/_core.scss +1 -1
  4. data/app/assets/stylesheets/geoblacklight_admin/modules/_icons.scss +9 -0
  5. data/app/controllers/admin/document_data_dictionaries_controller.rb +126 -0
  6. data/app/controllers/admin/document_data_dictionary_entries_controller.rb +124 -0
  7. data/app/controllers/admin/document_distributions_controller.rb +0 -38
  8. data/app/controllers/admin/import_distributions_controller.rb +126 -0
  9. data/app/javascript/index.js +1 -1
  10. data/app/jobs/import_distributions_run_job.rb +32 -0
  11. data/app/jobs/import_document_distribution_job.rb +23 -0
  12. data/app/models/document.rb +5 -0
  13. data/app/models/document_data_dictionary/csv_header_validator.rb +30 -0
  14. data/app/models/document_data_dictionary.rb +39 -0
  15. data/app/models/document_data_dictionary_entry.rb +9 -0
  16. data/app/models/import_distribution/csv_header_validator.rb +32 -0
  17. data/app/models/import_distribution.rb +55 -0
  18. data/app/models/import_distribution_state_machine.rb +14 -0
  19. data/app/models/import_distribution_transition.rb +26 -0
  20. data/app/models/import_document_distribution.rb +25 -0
  21. data/app/models/import_document_distribution_state_machine.rb +13 -0
  22. data/app/models/import_document_distribution_transition.rb +19 -0
  23. data/app/views/admin/document_data_dictionaries/_data_dictionaries_table.html.erb +40 -0
  24. data/app/views/admin/document_data_dictionaries/_document_data_dictionary.html.erb +37 -0
  25. data/app/views/admin/document_data_dictionaries/_document_data_dictionary.json.jbuilder +2 -0
  26. data/app/views/admin/document_data_dictionaries/_form.html.erb +17 -0
  27. data/app/views/admin/document_data_dictionaries/edit.html.erb +12 -0
  28. data/app/views/admin/document_data_dictionaries/index.html.erb +45 -0
  29. data/app/views/admin/document_data_dictionaries/index.json.jbuilder +1 -0
  30. data/app/views/admin/document_data_dictionaries/new.html.erb +78 -0
  31. data/app/views/admin/document_data_dictionaries/show.html.erb +78 -0
  32. data/app/views/admin/document_data_dictionaries/show.json.jbuilder +1 -0
  33. data/app/views/admin/document_data_dictionary_entries/_form.html.erb +19 -0
  34. data/app/views/admin/document_data_dictionary_entries/edit.html.erb +12 -0
  35. data/app/views/admin/document_data_dictionary_entries/new.html.erb +16 -0
  36. data/app/views/admin/document_distributions/index.html.erb +2 -2
  37. data/app/views/admin/documents/_form_nav.html.erb +4 -0
  38. data/app/views/admin/import_distributions/_form.html.erb +21 -0
  39. data/app/views/admin/import_distributions/_import_distribution.json.jbuilder +5 -0
  40. data/app/views/admin/import_distributions/_show_failed_tab.html.erb +36 -0
  41. data/app/views/admin/import_distributions/_show_success_tab.html.erb +35 -0
  42. data/app/views/admin/import_distributions/edit.html.erb +8 -0
  43. data/app/views/admin/import_distributions/index.html.erb +58 -0
  44. data/app/views/admin/import_distributions/index.json.jbuilder +3 -0
  45. data/app/views/admin/import_distributions/new.html.erb +7 -0
  46. data/app/views/admin/import_distributions/show.html.erb +121 -0
  47. data/app/views/admin/import_distributions/show.json.jbuilder +3 -0
  48. data/app/views/admin/imports/index.html.erb +2 -2
  49. data/app/views/admin/shared/_navbar.html.erb +2 -2
  50. data/app/views/catalog/_gbl_admin_data_dictionaries.html.erb +3 -0
  51. data/app/views/catalog/_show_gbl_admin_data_dictionaries.html.erb +44 -0
  52. data/app/views/catalog/data_dictionaries.html.erb +12 -0
  53. data/db/migrate/20241204163117_create_document_data_dictionaries.rb +14 -0
  54. data/db/migrate/20241218174455_create_document_data_dictionary_entries.rb +17 -0
  55. data/db/migrate/20250113213655_import_distributions.rb +56 -0
  56. data/lib/generators/geoblacklight_admin/config_generator.rb +61 -4
  57. data/lib/generators/geoblacklight_admin/templates/btaa_sample_document_data_dictionary_entries.csv +9 -0
  58. data/lib/generators/geoblacklight_admin/templates/btaa_sample_document_distributions.csv +17 -0
  59. data/lib/geoblacklight_admin/routes/data_dictionariesable.rb +17 -0
  60. data/lib/geoblacklight_admin/version.rb +1 -1
  61. metadata +49 -2
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ # ImportDistribution class
6
+ class ImportDistribution < ApplicationRecord
7
+ include ActiveModel::Validations
8
+
9
+ # Callbacks (keep at top)
10
+ after_commit :set_csv_file_attributes, if: :persisted?
11
+
12
+ # Associations
13
+ has_one_attached :csv_file
14
+ has_many :document_distributions, dependent: :destroy
15
+ has_many :import_document_distributions, dependent: :destroy
16
+ has_many :import_distribution_transitions, autosave: false, dependent: :destroy
17
+
18
+ # Validations
19
+ validates :csv_file, attached: true, content_type: {in: "text/csv", message: "is not a CSV file"}
20
+
21
+ validates_with ImportDistribution::CsvHeaderValidator
22
+
23
+ # States
24
+ include Statesman::Adapters::ActiveRecordQueries[
25
+ transition_class: ImportDistributionTransition,
26
+ initial_state: :created
27
+ ]
28
+
29
+ def state_machine
30
+ @state_machine ||= ImportDistributionStateMachine.new(self, transition_class: ImportDistributionTransition)
31
+ end
32
+
33
+ def set_csv_file_attributes
34
+ parsed = CSV.parse(csv_file.download)
35
+
36
+ update_columns(
37
+ headers: parsed[0],
38
+ row_count: parsed.size - 1,
39
+ content_type: csv_file.content_type.to_s,
40
+ filename: csv_file.filename.to_s,
41
+ extension: csv_file.filename.extension.to_s
42
+ )
43
+ end
44
+
45
+ def run!
46
+ # @TODO: guard this call, unless mappings_valid?
47
+
48
+ # Queue Job
49
+ ImportDistributionsRunJob.perform_later(self)
50
+
51
+ # Capture State
52
+ state_machine.transition_to!(:imported)
53
+ save
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Import Distribution Statesman
4
+ class ImportDistributionStateMachine
5
+ include Statesman::Machine
6
+
7
+ state :created, initial: true
8
+ state :imported
9
+ state :success
10
+ state :failed
11
+
12
+ transition from: :created, to: [:imported]
13
+ transition from: :imported, to: %i[success failed]
14
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add Import Distribution Statesman Transitions
4
+ class ImportDistributionTransition < ApplicationRecord
5
+ include Statesman::Adapters::ActiveRecordTransition
6
+
7
+ # If your transition table doesn't have the default `updated_at` timestamp column,
8
+ # you'll need to configure the `updated_timestamp_column` option, setting it to
9
+ # another column name (e.g. `:updated_on`) or `nil`.
10
+ #
11
+ # self.updated_timestamp_column = :updated_on
12
+ # self.updated_timestamp_column = nil
13
+
14
+ belongs_to :import_distribution, inverse_of: :import_distribution_transitions
15
+
16
+ after_destroy :update_most_recent, if: :most_recent?
17
+
18
+ private
19
+
20
+ def update_most_recent
21
+ last_transition = import_distribution.import_distribution_transitions.order(:sort_key).last
22
+ return if last_transition.blank?
23
+
24
+ last_transition.update_column(:most_recent, true)
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ImportDocumentDistribution class
4
+ class ImportDocumentDistribution < ApplicationRecord
5
+ has_many :import_document_distribution_transitions, autosave: false, dependent: :destroy
6
+
7
+ include Statesman::Adapters::ActiveRecordQueries[
8
+ transition_class: ImportDocumentDistributionTransition,
9
+ initial_state: :queued
10
+ ]
11
+
12
+ def state_machine
13
+ @state_machine ||= ImportDocumentDistributionStateMachine.new(self, transition_class: ImportDocumentDistributionTransition)
14
+ end
15
+
16
+ def to_hash
17
+ {
18
+ friendlier_id: friendlier_id,
19
+ reference_type: ReferenceType.find_by(name: reference_type),
20
+ url: distribution_url,
21
+ label: label,
22
+ import_distribution_id: import_distribution_id
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ImportDocumentDistribution Statesman
4
+ class ImportDocumentDistributionStateMachine
5
+ include Statesman::Machine
6
+
7
+ state :queued, initial: true
8
+ state :success
9
+ state :failed
10
+
11
+ transition from: :queued, to: %i[success failed]
12
+ transition from: :failed, to: :success
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Add ImportDocumentDistribution Statesman Transitions
4
+ class ImportDocumentDistributionTransition < ApplicationRecord
5
+ include Statesman::Adapters::ActiveRecordTransition
6
+
7
+ belongs_to :import_document_distribution, inverse_of: :import_document_distribution_transitions
8
+
9
+ after_destroy :update_most_recent, if: :most_recent?
10
+
11
+ private
12
+
13
+ def update_most_recent
14
+ last_transition = import_document_distribution.import_document_distribution_transitions.order(:sort_key).last
15
+ return if last_transition.blank?
16
+
17
+ last_transition.update_column(:most_recent, true)
18
+ end
19
+ end
@@ -0,0 +1,40 @@
1
+ <div class="table-responsive">
2
+ <table class="table table-striped table-bordered sortable">
3
+ <thead class="thead-dark">
4
+ <tr>
5
+ <th>Name</th>
6
+ <th>Description</th>
7
+ <th>Staff Notes</th>
8
+ <th>Tags</th>
9
+ <th>Entries</th>
10
+ <th colspan="2">Actions</th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ <% document_data_dictionaries.each do |document_data_dictionary| %>
15
+ <tr>
16
+ <td><%= link_to(document_data_dictionary.name, admin_document_document_data_dictionary_path(document_data_dictionary.friendlier_id, document_data_dictionary)) %></td>
17
+ <td>
18
+ <%= document_data_dictionary.description %>
19
+ <span class="sr-only"><%= document_data_dictionary.inspect %></span>
20
+ </td>
21
+ <td>
22
+ <%= document_data_dictionary.staff_notes %>
23
+ </td>
24
+ <td>
25
+ <%= document_data_dictionary.tags %>
26
+ </td>
27
+ <td>
28
+ <%= link_to "#{document_data_dictionary.document_data_dictionary_entries.count} entries", admin_document_document_data_dictionary_path(document_data_dictionary.friendlier_id, document_data_dictionary) %>
29
+ </td>
30
+ <td>
31
+ <%= link_to 'Edit', edit_admin_document_document_data_dictionary_path(document_data_dictionary.friendlier_id, document_data_dictionary) %>
32
+ </td>
33
+ <td>
34
+ <%= link_to 'Destroy', admin_document_document_data_dictionary_path(document_data_dictionary.friendlier_id, document_data_dictionary), method: :delete, data: { confirm: 'Are you sure?' } %>
35
+ </td>
36
+ </tr>
37
+ <% end %>
38
+ </tbody>
39
+ </table>
40
+ </div>
@@ -0,0 +1,37 @@
1
+ <%- @page_title = "GBL♦Admin - Document - Data Dictionaries" %>
2
+
3
+ <div id="<%= dom_id document_data_dictionary %>">
4
+ <h2>
5
+ <%= document_data_dictionary.name %>
6
+ <%= link_to '~ Edit Data Dictionary', edit_admin_document_document_data_dictionary_path, { class: 'btn btn-primary float-right' } %>
7
+ </h2>
8
+
9
+ <table class="table table-bordered">
10
+ <thead class="thead-dark">
11
+ <tr>
12
+ <th class="header" style="width:300px;">Attribute</th>
13
+ <th class="header">Value</th>
14
+ </tr>
15
+ </thead>
16
+ <tr>
17
+ <th>Friendlier Id</th>
18
+ <td><%= document_data_dictionary.friendlier_id %></td>
19
+ </tr>
20
+ <tr>
21
+ <th>Name</th>
22
+ <td><%= document_data_dictionary.name %></td>
23
+ </tr>
24
+ <tr>
25
+ <th>Description</th>
26
+ <td><%= document_data_dictionary.description %></td>
27
+ </tr>
28
+ <tr>
29
+ <th>Staff Notes</th>
30
+ <td><%= document_data_dictionary.staff_notes %></td>
31
+ </tr>
32
+ <tr>
33
+ <th>Tags</th>
34
+ <td><%= document_data_dictionary.tags %></td>
35
+ </tr>
36
+ </table>
37
+ </div>
@@ -0,0 +1,2 @@
1
+ json.extract! document_data_dictionary, :id, :friendlier_id, :label, :type, :values, :definition, :definition_source, :parent_friendlier_id, :created_at, :updated_at
2
+ json.url document_data_dictionary_url(document_data_dictionary, format: :json)
@@ -0,0 +1,17 @@
1
+ <%= simple_form_for([:admin, @document, @document_data_dictionary]) 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 :name, input_html: { class: 'form-control', autofocus: true } %>
8
+ <%= f.input :description, input_html: { class: 'form-control' } %>
9
+ <%= f.input :staff_notes, input_html: { class: 'form-control' } %>
10
+ <%= f.input :tags, input_html: { class: "form-control mb-2", placeholder: "Comma-separated tags (Optional)", data: { controller: "taginput" } } %>
11
+ <%= f.file_field :csv_file, direct_upload: true %>
12
+ </div>
13
+
14
+ <div class="form-group mt-3">
15
+ <%= f.submit class: 'btn btn-primary' %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <% content_for :title, "Editing document data dictionary" %>
2
+
3
+ <h1>Editing document data dictionary</h1>
4
+
5
+ <%= render "form", document_data_dictionary: @document_data_dictionary %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%= link_to "Show this document data dictionary", admin_document_document_data_dictionary_path(@document, @document_data_dictionary) %> |
11
+ <%= link_to "Back to document data dictionaries", admin_document_document_data_dictionaries_path(@document) %>
12
+ </div>
@@ -0,0 +1,45 @@
1
+ <%- @page_title = "GBL♦Admin - Document - Data Dictionaries" %>
2
+
3
+ <div class="row mb-2">
4
+ <div class="col">
5
+ <h1 style="width:100%;">
6
+ Document &middot; Data Dictionaries
7
+
8
+ <%= link_to '+ New Data Dictionary', new_admin_document_document_data_dictionary_path, { class: 'btn btn-primary float-right' } %>
9
+ </h1>
10
+ <% if params[:document_id] %>
11
+ <h2 class='h3'>
12
+ <%= link_to(@document.title, admin_document_path(@document)) %>
13
+ &middot;
14
+ <%= @document_data_dictionaries.count %> data dictionaries
15
+ </h2>
16
+ <% else %>
17
+ <h2 class='h3'>Data Dictionaries</h2>
18
+ <% end %>
19
+
20
+ <% if @pagy %>
21
+ <h6>
22
+ <span class='float-left mt-3'>
23
+ <%== pagy_info(@pagy, 'data dictionaries'.pluralize(@pagy.count)) %>
24
+ </span>
25
+ <span class='float-right'>
26
+ <%== pagy_bootstrap_nav(@pagy) %>
27
+ </span>
28
+ </h6>
29
+ <% end %>
30
+
31
+ <%= render partial: 'data_dictionaries_table', locals: { document_data_dictionaries: @document_data_dictionaries } %>
32
+
33
+ <% if @pagy %>
34
+ <h6>
35
+ <span class='float-left mt-3'>
36
+ <%== pagy_info(@pagy, 'data dictionaries'.pluralize(@pagy.count)) %>
37
+ </span>
38
+ <span class='float-right'>
39
+ <%== pagy_bootstrap_nav(@pagy) %>
40
+ </span>
41
+ </h6>
42
+ <% end %>
43
+ </div>
44
+ </div>
45
+ </div>
@@ -0,0 +1 @@
1
+ json.array! @document_data_dictionaries, partial: "document_data_dictionaries/document_data_dictionary", as: :document_data_dictionary
@@ -0,0 +1,78 @@
1
+ <div class="row mb-2">
2
+ <div class="col">
3
+ <%= link_to "Back to document data dictionaries", admin_document_document_data_dictionaries_path(@document) %>
4
+
5
+ <h1 style="width:100%;">
6
+ <%= @document.title %> &middot; New Data Dictionary
7
+ </h1>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="row">
12
+ <div class="col-5">
13
+ <%= render "form", document_data_dictionary: @document_data_dictionary %>
14
+ </div>
15
+
16
+ <div class="col-6">
17
+ <h4>Example Data Dictionary CSV File</h4>
18
+ <table class="table table-bordered">
19
+ <thead>
20
+ <tr>
21
+ <th>friendlier_id*</th>
22
+ <th>field_name*</th>
23
+ <th>field_type*</th>
24
+ <th>values*</th>
25
+ <th>definition</th>
26
+ <th>definition_source</th>
27
+ <th>parent_field_name</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td>999-0010a</td>
33
+ <td>Institution</td>
34
+ <td>string</td>
35
+ <td>University of Minnesota</td>
36
+ <td>The name of the institution</td>
37
+ <td>https://www.umn.edu</td>
38
+ <td>999-0010UMN</td>
39
+ </tr>
40
+ <tr>
41
+ <td>999-0010a</td>
42
+ <td>Institution</td>
43
+ <td>string</td>
44
+ <td>University of Minnesota Duluth</td>
45
+ <td>The name of the institution</td>
46
+ <td>https://www.d.umn.edu</td>
47
+ <td>999-0010UMN</td>
48
+ </tr>
49
+ <tr>
50
+ <td>...</td>
51
+ <td>...</td>
52
+ <td>...</td>
53
+ <td>...</td>
54
+ <td>...</td>
55
+ <td>...</td>
56
+ </tr>
57
+ </tbody>
58
+ </table>
59
+
60
+ <h5>CSV File Column Definitions</h5>
61
+ <dl>
62
+ <dt>friendlier_id</dt>
63
+ <dd>The associated document's friendlier id</dd>
64
+ <dt>field_name</dt>
65
+ <dd>The name of the field</dd>
66
+ <dt>field_type</dt>
67
+ <dd>The type of the field</dd>
68
+ <dt>values</dt>
69
+ <dd>The values of the field</dd>
70
+ <dt>definition</dt>
71
+ <dd>The definition of the field</dd>
72
+ <dt>definition_source</dt>
73
+ <dd>The source of the definition</dd>
74
+ <dt>parent_field_name</dt>
75
+ <dd>The parent field's name</dd>
76
+ </dl>
77
+ </div>
78
+ </div>
@@ -0,0 +1,78 @@
1
+ <%- @page_title = "GBL♦Admin - Document - Data Dictionaries" %>
2
+
3
+ <div class="row mb-2">
4
+ <div class="col">
5
+ <%= link_to "Back to document data dictionaries", admin_document_document_data_dictionaries_path(@document) %>
6
+
7
+ <h1 style="width:100%;">
8
+ <%= @document.title %> &middot; Data Dictionaries &middot; <%= @document_data_dictionary.name %>
9
+
10
+ <%= link_to '+ New Entry', new_admin_document_document_data_dictionary_document_data_dictionary_entry_path(@document, @document_data_dictionary), { class: 'btn btn-primary float-right' } %>
11
+ </h1>
12
+ </div>
13
+ </div>
14
+
15
+ <div class="row">
16
+ <div class="col-12">
17
+ <h6>
18
+ <span class='float-left mt-3'>
19
+ <%== pagy_info(@pagy) %>
20
+ </span>
21
+ <span class='float-right'>
22
+ <%== pagy_bootstrap_nav(@pagy) %>
23
+ </span>
24
+ </h6>
25
+
26
+ <div class="table-responsive">
27
+ <table class="table table-striped table-bordered sortable">
28
+ <thead class="thead-dark">
29
+ <tr>
30
+ <th class="header">field_name</th>
31
+ <th class="header">field_type</th>
32
+ <th class="header">values</th>
33
+ <th class="header">definition</th>
34
+ <th class="header">definition_source</th>
35
+ <th class="header">parent_field_name</th>
36
+ <th class="header">Reorder</th>
37
+ <th class="header" colspan="2">Actions</th>
38
+ </tr>
39
+ </thead>
40
+ <tbody>
41
+ <% @document_data_dictionary.document_data_dictionary_entries.each do |entry| %>
42
+ <tr data-id="<%=entry.id%>">
43
+ <td><%= entry.field_name %></td>
44
+ <td><%= entry.field_type %></td>
45
+ <td><%= entry.values %></td>
46
+ <td><%= entry.definition %></td>
47
+ <td><%= entry.definition_source %></td>
48
+ <td><%= entry.parent_field_name %></td>
49
+ <td class="handle" style="text-align:center">&varr;</td>
50
+ <td>
51
+ <%= link_to 'Edit', edit_admin_document_document_data_dictionary_document_data_dictionary_entry_path(@document, @document_data_dictionary, entry.id) %>
52
+ </td>
53
+ <td>
54
+ <%= link_to 'Destroy', admin_document_document_data_dictionary_document_data_dictionary_entry_path(@document, @document_data_dictionary, entry.id), method: :delete, data: { confirm: 'Are you sure?' } %>
55
+ </td>
56
+ </tr>
57
+ <% end %>
58
+ </tbody>
59
+ </table>
60
+ </div>
61
+
62
+ <h6>
63
+ <span class='float-left mt-3'>
64
+ <%== pagy_info(@pagy) %>
65
+ </span>
66
+ <span class='float-right'>
67
+ <%== pagy_bootstrap_nav(@pagy) %>
68
+ </span>
69
+ </h6>
70
+ </div>
71
+ </div>
72
+
73
+ <script>
74
+ GBLADMIN.SortElements(
75
+ $("tbody"),
76
+ "<%= sort_admin_document_document_data_dictionary_document_data_dictionary_entries_path(@document, @document_data_dictionary) %>"
77
+ );
78
+ </script>
@@ -0,0 +1 @@
1
+ json.partial! "document_data_dictionaries/document_data_dictionary", document_data_dictionary: @document_data_dictionary
@@ -0,0 +1,19 @@
1
+ <%= simple_form_for([:admin, @document, @document_data_dictionary, @document_data_dictionary_entry]) 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 :document_data_dictionary_id, as: :hidden, input_html: { value: @document_data_dictionary.id } %>
8
+ <%= f.input :field_name, input_html: { class: 'form-control', autofocus: true } %>
9
+ <%= f.input :field_type, input_html: { class: 'form-control' } %>
10
+ <%= f.input :values, input_html: { class: 'form-control' } %>
11
+ <%= f.input :definition, input_html: { class: 'form-control' } %>
12
+ <%= f.input :definition_source, input_html: { class: 'form-control' } %>
13
+ <%= f.input :parent_field_name, input_html: { class: 'form-control' } %>
14
+ </div>
15
+
16
+ <div class="form-group">
17
+ <%= f.submit class: 'btn btn-primary' %>
18
+ </div>
19
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <% content_for :title, "Editing document data dictionary entry" %>
2
+
3
+ <h1>Editing document data dictionary entry</h1>
4
+
5
+ <%= render "form", document_data_dictionary_entry: @document_data_dictionary_entry %>
6
+
7
+ <br>
8
+
9
+ <div>
10
+ <%= link_to "Show this document data dictionary entry", admin_document_document_data_dictionary_document_data_dictionary_entry_path(@document, @document_data_dictionary, @document_data_dictionary_entry) %> |
11
+ <%= link_to "Back to document data dictionary entries", admin_document_document_data_dictionary_document_data_dictionary_entries_path(@document, @document_data_dictionary) %>
12
+ </div>
@@ -0,0 +1,16 @@
1
+ <div class="row mb-2">
2
+ <div class="col">
3
+ <%= link_to "Back to document data dictionaries", admin_document_document_data_dictionaries_path(@document) %>
4
+
5
+ <h1 style="width:100%;">
6
+ <%= @document.title %> &middot; New Data Dictionary Entry
7
+ </h1>
8
+ </div>
9
+ </div>
10
+
11
+ <div class="row">
12
+ <div class="col-5">
13
+ <%= render "form", document_data_dictionary_entry: @document_data_dictionary_entry %>
14
+
15
+ <%= link_to "Back to document data dictionary entries", admin_document_document_data_dictionary_document_data_dictionary_entries_path(@document, @document_data_dictionary) %>
16
+ </div>
@@ -6,12 +6,12 @@
6
6
  Document &middot; Distributions
7
7
 
8
8
  <% if params[:document_id] %>
9
- <%= link_to '+ Import CSV', import_admin_document_document_distributions_path(@document), { class: 'btn btn-primary float-right' } %>
9
+ <%= link_to '+ Import CSV', new_admin_import_distribution_path, { class: 'btn btn-primary float-right' } %>
10
10
 
11
11
  <%= link_to '+ New Distribution', new_admin_document_document_distribution_path(@document), { class: 'btn btn-primary float-right mr-2' } %>
12
12
  <% else %>
13
13
  <%= link_to '- Delete CSV', destroy_all_admin_document_distributions_path, { class: 'btn btn-danger float-right' } %>
14
- <%= link_to '+ Import CSV', import_admin_document_distributions_path, { class: 'btn btn-primary float-right mr-4' } %>
14
+ <%= link_to '+ Import CSV', new_admin_import_distribution_path, { class: 'btn btn-primary float-right mr-4' } %>
15
15
  <% end %>
16
16
  </h1>
17
17
 
@@ -32,6 +32,10 @@
32
32
  Additional Assets
33
33
  <span class="badge badge-light"><%= @document.document_assets.count %></span>
34
34
  <% end %>
35
+ <%= link_to admin_document_document_data_dictionaries_url(@document), class: "ml-2" do %>
36
+ Data Dictionaries
37
+ <span class="badge badge-light"><%= @document.document_data_dictionaries.count %></span>
38
+ <% end %>
35
39
  <%= link_to admin_document_document_distributions_url(@document), class: "ml-2" do %>
36
40
  Distributions
37
41
  <% end %>
@@ -0,0 +1,21 @@
1
+ <% if @import_distribution.errors.any? %>
2
+ <div class="alert alert-danger mb-4" role="alert">
3
+ <h2 class="h4" class="alert-heading"><%= pluralize(@import_distribution.errors.count, "error") %> prohibited this import distribution from being saved</h2>
4
+ <ol class="mb-0">
5
+ <% @import_distribution.errors.full_messages.each do |msg| %>
6
+ <li><%= msg %></li>
7
+ <% end %>
8
+ </ol>
9
+ </div>
10
+ <% end %>
11
+
12
+ <div class="form-inputs">
13
+ <%= f.input :name, {autofocus: true} %>
14
+ <%= f.input :source %>
15
+ <%= f.input :description %>
16
+ <%= f.file_field :csv_file, direct_upload: true %>
17
+ </div>
18
+
19
+ <div class="form-actions">
20
+ <%= f.button :submit, "+ Create Import Distributions", {class: 'btn btn-primary'} %>
21
+ </div>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ json.extract! import_distribution, :id, :name, :filename, :source, :description, :row_count, :headers, :encoding, :content_type,
4
+ :extension, :validity, :validation_result, :created_at, :updated_at
5
+ json.url import_distribution_url(import_distribution, format: :json)
@@ -0,0 +1,36 @@
1
+ <h6>
2
+ <span class='float-left mt-3'>
3
+ <%== pagy_info(@pagy_failed) %>
4
+ </span>
5
+ <span class='float-right'>
6
+ <%== pagy_bootstrap_nav(@pagy_failed) %>
7
+ </span>
8
+ </h6>
9
+
10
+ <table class="table table-striped">
11
+ <thead>
12
+ <tr>
13
+ <th>State</th>
14
+ <th>Title</th>
15
+ <th>Identifier</th>
16
+ <th>Reason</th>
17
+ </tr>
18
+ </thead>
19
+ <tbody>
20
+ <% @import_failed_distributions.each_with_index do |distribution, index| %>
21
+ <tr>
22
+ <td>
23
+ <span class="badge badge-danger">
24
+ <%= distribution.state_machine.current_state %>
25
+ </span>
26
+ </td>
27
+ <td><%= distribution.friendlier_id %></td>
28
+ <td>
29
+ <%= link_to admin_import_distribution_path(@import_distribution, distribution) do %>
30
+ <%= distribution.state_machine&.last_transition&.metadata %>
31
+ <% end %>
32
+ </td>
33
+ </tr>
34
+ <% end %>
35
+ </tbody>
36
+ </table>