geoblacklight_admin 0.6.3 → 0.7.0

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