Skip to content

Commit

Permalink
Add project dataset select format
Browse files Browse the repository at this point in the history
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
  • Loading branch information
gbp committed Sep 30, 2024
1 parent 3568d9f commit 3d9ba30
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 6 deletions.
6 changes: 5 additions & 1 deletion app/controllers/alaveteli_pro/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/projects/extracts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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: []]

Check warning on line 74 in app/controllers/projects/extracts_controller.rb

View workflow job for this annotation

GitHub Actions / build

[rubocop] reported by reviewdog 🐶 Line is too long. [82/80] (https://rubystyle.guide#max-line-length) Raw Output: app/controllers/projects/extracts_controller.rb:74:81: C: Layout/LineLength: Line is too long. [82/80] (https://rubystyle.guide#max-line-length)
)
end

Expand Down
31 changes: 31 additions & 0 deletions app/javascript/controllers/projects/key_set/select_controller.js
Original file line number Diff line number Diff line change
@@ -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();
}
}
16 changes: 15 additions & 1 deletion app/models/dataset/key.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20210114161442
# Schema version: 20240926164308
#
# Table name: dataset_keys
#
Expand All @@ -10,6 +10,7 @@
# order :integer
# created_at :datetime not null
# updated_at :datetime not null
# options :jsonb
#

##
Expand All @@ -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
Expand All @@ -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
9 changes: 9 additions & 0 deletions app/models/dataset/value.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
5 changes: 5 additions & 0 deletions app/views/alaveteli_pro/projects/_key_set.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
data: { action: 'change->projects--key-set#updateKey' },
autocomplete: 'off' %>
</div>

<% if lookup_context.exists?("alaveteli_pro/projects/_#{key.format}_key") %>
<%= render partial: "alaveteli_pro/projects/#{key.format}_key",
locals: { form: f, key: key } %>
<% end %>
</div>

<div class="project-key-set__key__remove-question">
Expand Down
41 changes: 41 additions & 0 deletions app/views/alaveteli_pro/projects/_select_key.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<%= form.fields_for :options, key.options do |f| %>
<div class="project-key-set__key__value">
<%= f.label :select_allow_blank do %>
<%= f.check_box :select_allow_blank, checked: key.select_allow_blank?, autocomplete: 'off' %>
<%= _('Allow blank') %>
<% end %>
</div>

<div class="project-key-set__key__value">
<%= f.label :select_allow_muliple do %>
<%= f.check_box :select_allow_muliple, checked: key.select_allow_muliple?, autocomplete: 'off' %>
<%= _('Allow muliple') %>
<% end %>
</div>

<%= 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') %>
<ul>
<% key.select_options.each_with_index do |option, index| %>
<li>
<%= option %>
<%= hidden_field_tag "#{f.object_name}[select_options][]", option %>
<%= button_tag class: 'button-unstyled', data: { action: 'click->projects--key-set--select#removeOption' } do %>
<%= _('Remove') %>
<% end %>
</li>
<% end %>
</ul>
<div class="row collapse postfix-radius">
<div class="small-10 columns">
<%= text_field_tag "select_option", nil, data: { projects__key_set__select_target: 'newInput' } %>
</div>
<div class="small-2 columns">
<%= button_tag _('Add'), class: 'button-tertiary postfix', data: { action: 'click->projects--key-set--select#addOption' } %>
</div>
</div>
<% end %>
<% end %>
4 changes: 4 additions & 0 deletions app/views/projects/dataset/keys/_select_key.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div class="dataset-key">
<%= f.label :value, key.title %>
<%= f.select :value, key.select_options, { include_blank: key.select_allow_blank? }, multiple: key.select_allow_muliple? %>
</div>
5 changes: 5 additions & 0 deletions db/migrate/20240926164308_add_options_to_dataset_key.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddOptionsToDatasetKey < ActiveRecord::Migration[7.0]
def change
add_column :dataset_keys, :options, :jsonb, default: {}
end
end
1 change: 1 addition & 0 deletions doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion spec/factories/dataset_keys.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20210114161442
# Schema version: 20240926164308
#
# Table name: dataset_keys
#
Expand All @@ -10,6 +10,7 @@
# order :integer
# created_at :datetime not null
# updated_at :datetime not null
# options :jsonb
#

FactoryBot.define do
Expand All @@ -24,6 +25,10 @@
format { 'text' }
end

trait :select do
format { 'select' }
end

trait :numeric do
format { 'numeric' }
end
Expand Down
13 changes: 11 additions & 2 deletions spec/models/dataset/key_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# == Schema Information
# Schema version: 20210114161442
# Schema version: 20240926164308
#
# Table name: dataset_keys
#
Expand All @@ -10,6 +10,7 @@
# order :integer
# created_at :datetime not null
# updated_at :datetime not null
# options :jsonb
#

require 'spec_helper'
Expand Down Expand Up @@ -63,6 +64,8 @@
is_expected.not_to be_valid
key.format = 'text'
is_expected.to be_valid
key.format = 'select'
is_expected.to be_valid
key.format = 'numeric'
is_expected.to be_valid
key.format = 'boolean'
Expand All @@ -75,7 +78,8 @@

it 'returns title/format key hash' do
is_expected.to eq(
{ 'Text' => :text, 'Numeric' => :numeric, 'Yes/No' => :boolean }
{ 'Text' => :text, 'Select' => :select, 'Numeric' => :numeric,
'Yes/No' => :boolean }
)
end
end
Expand All @@ -88,6 +92,11 @@
it { is_expected.to eq described_class::FORMATS[:text][:regexp] }
end

context 'select format' do
let(:key) { FactoryBot.build(:dataset_key, :select) }
it { is_expected.to eq described_class::FORMATS[:select][:regexp] }
end

context 'numeric format' do
let(:key) { FactoryBot.build(:dataset_key, :numeric) }
it { is_expected.to eq described_class::FORMATS[:numeric][:regexp] }
Expand Down

0 comments on commit 3d9ba30

Please sign in to comment.