From 148b23580d30a4b314d255088e774f8c7906baff Mon Sep 17 00:00:00 2001 From: Graeme Porteous Date: Fri, 27 Sep 2024 10:16:59 +0100 Subject: [PATCH] Add project dataset select format Allow project owners to add questions with a pre set list of options which can be selected when extracting information from requests. There are also options to allow blank value or multiple values, these effect how the form select input is rendered in the extracting sidebar. Fixes #8117 --- .../alaveteli_pro/projects_controller.rb | 6 ++- .../projects/extracts_controller.rb | 2 +- .../projects/key_set/select_controller.js | 31 ++++++++++++++ app/models/dataset/key.rb | 16 +++++++- app/models/dataset/value.rb | 9 ++++ .../alaveteli_pro/projects/_key_set.html.erb | 5 +++ .../projects/_select_key.html.erb | 41 +++++++++++++++++++ .../dataset/keys/_select_key.html.erb | 4 ++ ...240926164308_add_options_to_dataset_key.rb | 5 +++ doc/CHANGES.md | 1 + spec/factories/dataset_keys.rb | 3 +- spec/models/dataset/key_spec.rb | 3 +- 12 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 app/javascript/controllers/projects/key_set/select_controller.js create mode 100644 app/views/alaveteli_pro/projects/_select_key.html.erb create mode 100644 app/views/projects/dataset/keys/_select_key.html.erb create mode 100644 db/migrate/20240926164308_add_options_to_dataset_key.rb diff --git a/app/controllers/alaveteli_pro/projects_controller.rb b/app/controllers/alaveteli_pro/projects_controller.rb index d4c589aede..93cdbbfbe7 100644 --- a/app/controllers/alaveteli_pro/projects_controller.rb +++ b/app/controllers/alaveteli_pro/projects_controller.rb @@ -141,7 +141,11 @@ def project_params when 'edit_key_set', 'update_key_set' params.fetch(:project, {}).permit( key_set_attributes: [ - :id, keys_attributes: %i[id title format order _destroy] + :id, keys_attributes: [ + :id, :title, :format, :order, :_destroy, options: [ + :select_allow_blank, :select_allow_muliple, { select_options: [] } + ] + ] ] ) when 'edit_contributors', 'update_contributors' diff --git a/app/controllers/projects/extracts_controller.rb b/app/controllers/projects/extracts_controller.rb index 9cc041ab24..1014ebb90e 100644 --- a/app/controllers/projects/extracts_controller.rb +++ b/app/controllers/projects/extracts_controller.rb @@ -71,7 +71,7 @@ def find_info_request def extract_params params.require(:extract).permit( - :dataset_key_set_id, values_attributes: [:dataset_key_id, :value] + :dataset_key_set_id, values_attributes: [:dataset_key_id, :value, value: []] ) end diff --git a/app/javascript/controllers/projects/key_set/select_controller.js b/app/javascript/controllers/projects/key_set/select_controller.js new file mode 100644 index 0000000000..c935b98f86 --- /dev/null +++ b/app/javascript/controllers/projects/key_set/select_controller.js @@ -0,0 +1,31 @@ +import { Controller } from "@hotwired/stimulus"; +import { streamUpdate } from "helpers/stream_update"; + +export default class extends Controller { + static targets = ["newInput"]; + static values = { name: String }; + + addOption(event) { + event.preventDefault(); + + const newValue = this.newInputTarget.value; + if (!newValue) return; + + const form = this.element.closest("form"); + const hiddenInput = document.createElement("input"); + + hiddenInput.type = "hidden"; + hiddenInput.name = this.nameValue; + hiddenInput.value = newValue; + form.appendChild(hiddenInput); + + streamUpdate(form); + } + + removeOption(event) { + event.preventDefault(); + + const li = event.target.closest("li"); + if (li) li.remove(); + } +} diff --git a/app/models/dataset/key.rb b/app/models/dataset/key.rb index f48db23ce0..2d4aef091f 100644 --- a/app/models/dataset/key.rb +++ b/app/models/dataset/key.rb @@ -1,5 +1,5 @@ # == Schema Information -# Schema version: 20210114161442 +# Schema version: 20240926164308 # # Table name: dataset_keys # @@ -10,6 +10,7 @@ # order :integer # created_at :datetime not null # updated_at :datetime not null +# options :jsonb # ## @@ -24,6 +25,7 @@ class Dataset::Key < ApplicationRecord FORMATS = { text: { title: _('Text'), regexp: /\A.*\z/m }, + select: { title: _('Select'), regexp: /\A.*\z/m }, numeric: { title: _('Numeric'), regexp: /\A[0-9,%\+\-\s]*\z/ }, boolean: { title: _('Yes/No'), regexp: /\A(0|1)\z/ } }.freeze @@ -40,4 +42,16 @@ def self.format_options def format_regexp FORMATS[format.to_sym][:regexp] end + + def select_options + options.fetch('select_options', []) + end + + def select_allow_blank? + options.fetch('select_allow_blank', '0').to_i == 1 + end + + def select_allow_muliple? + options.fetch('select_allow_muliple', '0').to_i == 1 + end end diff --git a/app/models/dataset/value.rb b/app/models/dataset/value.rb index 735b99a3b0..3e53dc2bd4 100644 --- a/app/models/dataset/value.rb +++ b/app/models/dataset/value.rb @@ -29,6 +29,15 @@ def title key.title end + def value=(new_value) + case key.format + when 'select' + super(new_value.to_a.reject(&:blank?).join(', ')) + else + super + end + end + def mapped_value case key.format when 'boolean' diff --git a/app/views/alaveteli_pro/projects/_key_set.html.erb b/app/views/alaveteli_pro/projects/_key_set.html.erb index 632a1433e8..aa8184285f 100644 --- a/app/views/alaveteli_pro/projects/_key_set.html.erb +++ b/app/views/alaveteli_pro/projects/_key_set.html.erb @@ -24,6 +24,11 @@ data: { action: 'change->projects--key-set#updateKey' }, autocomplete: 'off' %> + + <% if lookup_context.exists?("alaveteli_pro/projects/_#{key.format}_key") %> + <%= render partial: "alaveteli_pro/projects/#{key.format}_key", + locals: { form: f, key: key } %> + <% end %>
diff --git a/app/views/alaveteli_pro/projects/_select_key.html.erb b/app/views/alaveteli_pro/projects/_select_key.html.erb new file mode 100644 index 0000000000..a60b9947fe --- /dev/null +++ b/app/views/alaveteli_pro/projects/_select_key.html.erb @@ -0,0 +1,41 @@ +<%= form.fields_for :options, key.options do |f| %> +
+ <%= f.label :select_allow_blank do %> + <%= f.check_box :select_allow_blank, checked: key.select_allow_blank?, autocomplete: 'off' %> + <%= _('Allow blank') %> + <% end %> +
+ +
+ <%= f.label :select_allow_muliple do %> + <%= f.check_box :select_allow_muliple, checked: key.select_allow_muliple?, autocomplete: 'off' %> + <%= _('Allow muliple') %> + <% end %> +
+ + <%= content_tag(:div, class: "project-key-set__key__value", data: { + controller: "projects--key-set--select", + projects__key_set__select_name_value: "#{f.object_name}[select_options][]" + }) do %> + <%= f.label :select_options, _('Options') %> + +
+
+ <%= text_field_tag "select_option", nil, data: { projects__key_set__select_target: 'newInput' } %> +
+
+ <%= button_tag _('Add'), class: 'button-tertiary postfix', data: { action: 'click->projects--key-set--select#addOption' } %> +
+
+ <% end %> +<% end %> diff --git a/app/views/projects/dataset/keys/_select_key.html.erb b/app/views/projects/dataset/keys/_select_key.html.erb new file mode 100644 index 0000000000..cfebb4a910 --- /dev/null +++ b/app/views/projects/dataset/keys/_select_key.html.erb @@ -0,0 +1,4 @@ +
+ <%= f.label :value, key.title %> + <%= f.select :value, key.select_options, { include_blank: key.select_allow_blank? }, multiple: key.select_allow_muliple? %> +
diff --git a/db/migrate/20240926164308_add_options_to_dataset_key.rb b/db/migrate/20240926164308_add_options_to_dataset_key.rb new file mode 100644 index 0000000000..2ef98b5b0d --- /dev/null +++ b/db/migrate/20240926164308_add_options_to_dataset_key.rb @@ -0,0 +1,5 @@ +class AddOptionsToDatasetKey < ActiveRecord::Migration[7.0] + def change + add_column :dataset_keys, :options, :jsonb, default: {} + end +end diff --git a/doc/CHANGES.md b/doc/CHANGES.md index f72aad51cd..4bbe3ce8fd 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -2,6 +2,7 @@ ## Highlighted Features +* Add project dataset question "select" format (Graeme Porteous) * Add example logrotate configuration (Graeme Porteous) * Switch application server from Thin to Puma (Graeme Porteous) * Fix rendering invoices page when there are discounted Pro subscription (Graeme diff --git a/spec/factories/dataset_keys.rb b/spec/factories/dataset_keys.rb index 8af52b242f..ba5f4a3da2 100644 --- a/spec/factories/dataset_keys.rb +++ b/spec/factories/dataset_keys.rb @@ -1,5 +1,5 @@ # == Schema Information -# Schema version: 20210114161442 +# Schema version: 20240926164308 # # Table name: dataset_keys # @@ -10,6 +10,7 @@ # order :integer # created_at :datetime not null # updated_at :datetime not null +# options :jsonb # FactoryBot.define do diff --git a/spec/models/dataset/key_spec.rb b/spec/models/dataset/key_spec.rb index e266abadb4..499dad7387 100644 --- a/spec/models/dataset/key_spec.rb +++ b/spec/models/dataset/key_spec.rb @@ -1,5 +1,5 @@ # == Schema Information -# Schema version: 20210114161442 +# Schema version: 20240926164308 # # Table name: dataset_keys # @@ -10,6 +10,7 @@ # order :integer # created_at :datetime not null # updated_at :datetime not null +# options :jsonb # require 'spec_helper'