[#1421] replace master/slave by primary/secondary

This commit is contained in:
Pierre de La Morinerie 2018-06-27 14:31:34 +02:00 committed by Frederic Merizen
parent dad3bc092b
commit 0cebf60c46
8 changed files with 84 additions and 84 deletions

View file

@ -1,30 +1,30 @@
document.addEventListener('turbolinks:load', function() { document.addEventListener('turbolinks:load', function() {
var masters, i, master, slave, slaveOptions; var primaries, i, primary, secondary, secondaryOptions;
masters = document.querySelectorAll('select[data-slave-options]'); primaries = document.querySelectorAll('select[data-secondary-options]');
for (i = 0; i < masters.length; i++) { for (i = 0; i < primaries.length; i++) {
master = masters[i]; primary = primaries[i];
slave = document.querySelector('select[data-slave-id="' + master.dataset.masterId + '"]'); secondary = document.querySelector('select[data-secondary-id="' + primary.dataset.primaryId + '"]');
slaveOptions = JSON.parse(master.dataset.slaveOptions); secondaryOptions = JSON.parse(primary.dataset.secondaryOptions);
master.addEventListener('change', function(e) { primary.addEventListener('change', function(e) {
var option, options, element; var option, options, element;
while ((option = slave.firstChild)) { while ((option = secondary.firstChild)) {
slave.removeChild(option); secondary.removeChild(option);
} }
options = slaveOptions[e.target.value]; options = secondaryOptions[e.target.value];
for (i = 0; i < options.length; i++) { for (i = 0; i < options.length; i++) {
option = options[i]; option = options[i];
element = document.createElement("option"); element = document.createElement("option");
element.textContent = option; element.textContent = option;
element.value = option; element.value = option;
slave.appendChild(element); secondary.appendChild(element);
} }
slave.selectedIndex = 0; secondary.selectedIndex = 0;
}); });
} }
}); });

View file

@ -145,7 +145,7 @@ module NewUser
def champs_params def champs_params
params.permit(dossier: { params.permit(dossier: {
champs_attributes: [ champs_attributes: [
:id, :value, :master_value, :slave_value, :piece_justificative_file, value: [], :id, :value, :primary_value, :secondary_value, :piece_justificative_file, value: [],
etablissement_attributes: Champs::SiretChamp::ETABLISSEMENT_ATTRIBUTES etablissement_attributes: Champs::SiretChamp::ETABLISSEMENT_ATTRIBUTES
] ]
}) })

View file

@ -1,36 +1,36 @@
class Champs::LinkedDropDownListChamp < Champ class Champs::LinkedDropDownListChamp < Champ
attr_reader :master_value, :slave_value attr_reader :primary_value, :secondary_value
delegate :master_options, :slave_options, to: :type_de_champ delegate :primary_options, :secondary_options, to: :type_de_champ
after_initialize :unpack_value after_initialize :unpack_value
def unpack_value def unpack_value
if value.present? if value.present?
master, slave = JSON.parse(value) primary, secondary = JSON.parse(value)
else else
master = slave = '' primary = secondary = ''
end end
@master_value ||= master @primary_value ||= primary
@slave_value ||= slave @secondary_value ||= secondary
end end
def master_value=(value) def primary_value=(value)
@master_value = value @primary_value = value
pack_value pack_value
end end
def slave_value=(value) def secondary_value=(value)
@slave_value = value @secondary_value = value
pack_value pack_value
end end
def main_value_name def main_value_name
:master_value :primary_value
end end
private private
def pack_value def pack_value
self.value = JSON.generate([ master_value, slave_value ]) self.value = JSON.generate([ primary_value, secondary_value ])
end end
end end

View file

@ -1,31 +1,31 @@
class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypeDeChamp class TypesDeChamp::LinkedDropDownListTypeDeChamp < TypeDeChamp
MASTER_PATTERN = /^--(.*)--$/ PRIMARY_PATTERN = /^--(.*)--$/
def master_options def primary_options
master_options = unpack_options.map(&:first) primary_options = unpack_options.map(&:first)
if master_options.present? if primary_options.present?
master_options.unshift('') primary_options.unshift('')
end end
master_options primary_options
end end
def slave_options def secondary_options
slave_options = unpack_options.to_h secondary_options = unpack_options.to_h
if slave_options.present? if secondary_options.present?
slave_options[''] = [] secondary_options[''] = []
end end
slave_options secondary_options
end end
private private
def unpack_options def unpack_options
_, *options = drop_down_list.options _, *options = drop_down_list.options
chunked = options.slice_before(MASTER_PATTERN) chunked = options.slice_before(PRIMARY_PATTERN)
chunked.map do |chunk| chunked.map do |chunk|
master, *slave = chunk primary, *secondary = chunk
slave.unshift('') secondary.unshift('')
[MASTER_PATTERN.match(master)[1], slave] [PRIMARY_PATTERN.match(primary)[1], secondary]
end end
end end
end end

View file

@ -1,10 +1,10 @@
- if champ.drop_down_list && champ.drop_down_list.options.any? - if champ.drop_down_list && champ.drop_down_list.options.any?
- champ_id = champ.object_id - champ_id = champ.object_id
= form.select :master_value, = form.select :primary_value,
champ.master_options, champ.primary_options,
{ required: champ.mandatory? }, { required: champ.mandatory? },
{ data: { "slave-options" => champ.slave_options, "master-id" => champ_id } } { data: { "secondary-options" => champ.secondary_options, "primary-id" => champ_id } }
= form.select :slave_value, = form.select :secondary_value,
champ.slave_options[champ.master_value], champ.secondary_options[champ.primary_value],
{ required: champ.mandatory? }, { required: champ.mandatory? },
{ data: { "slave-id" => champ_id } } { data: { "secondary-id" => champ_id } }

View file

@ -6,13 +6,13 @@ feature 'linked dropdown lists' do
let(:list_items) do let(:list_items) do
<<~END_OF_LIST <<~END_OF_LIST
--Master 1-- --Primary 1--
Slave 1.1 Secondary 1.1
Slave 1.2 Secondary 1.2
--Master 2-- --Primary 2--
Slave 2.1 Secondary 2.1
Slave 2.2 Secondary 2.2
Slave 2.3 Secondary 2.3
END_OF_LIST END_OF_LIST
end end
let(:drop_down_list) { create(:drop_down_list, value: list_items) } let(:drop_down_list) { create(:drop_down_list, value: list_items) }
@ -26,22 +26,22 @@ feature 'linked dropdown lists' do
let(:user_dossier) { user.dossiers.first } let(:user_dossier) { user.dossiers.first }
scenario 'change master value, slave options are updated', js: true do scenario 'change primary value, secondary options are updated', js: true do
log_in(user.email, password, procedure) log_in(user.email, password, procedure)
fill_individual fill_individual
# Select a master value # Select a primary value
select('Master 2', from: master_id_for('linked dropdown')) select('Primary 2', from: primary_id_for('linked dropdown'))
# Slave menu reflects chosen master value # Secondary menu reflects chosen primary value
expect(page).to have_select(slave_id_for('linked dropdown'), options: ['', 'Slave 2.1', 'Slave 2.2', 'Slave 2.3']) expect(page).to have_select(secondary_id_for('linked dropdown'), options: ['', 'Secondary 2.1', 'Secondary 2.2', 'Secondary 2.3'])
# Select another master value # Select another primary value
select('Master 1', from: master_id_for('linked dropdown')) select('Primary 1', from: primary_id_for('linked dropdown'))
# Slave menu gets updated # Secondary menu gets updated
expect(page).to have_select(slave_id_for('linked dropdown'), options: ['', 'Slave 1.1', 'Slave 1.2']) expect(page).to have_select(secondary_id_for('linked dropdown'), options: ['', 'Secondary 1.1', 'Secondary 1.2'])
end end
private private
@ -64,13 +64,13 @@ feature 'linked dropdown lists' do
expect(page).to have_current_path(modifier_dossier_path(user_dossier)) expect(page).to have_current_path(modifier_dossier_path(user_dossier))
end end
def master_id_for(libelle) def primary_id_for(libelle)
find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for] find(:xpath, ".//label[contains(text()[normalize-space()], '#{libelle}')]")[:for]
end end
def slave_id_for(libelle) def secondary_id_for(libelle)
master_id = master_id_for(libelle) primary_id = primary_id_for(libelle)
link = find("\##{master_id}")['data-master-id'] link = find("\##{primary_id}")['data-primary-id']
find("[data-slave-id=\"#{link}\"]")['id'] find("[data-secondary-id=\"#{link}\"]")['id']
end end
end end

View file

@ -4,12 +4,12 @@ describe Champs::LinkedDropDownListChamp do
describe '#unpack_value' do describe '#unpack_value' do
let(:champ) { described_class.new(value: '["tata", "tutu"]') } let(:champ) { described_class.new(value: '["tata", "tutu"]') }
it { expect(champ.master_value).to eq('tata') } it { expect(champ.primary_value).to eq('tata') }
it { expect(champ.slave_value).to eq('tutu') } it { expect(champ.secondary_value).to eq('tutu') }
end end
describe '#pack_value' do describe '#pack_value' do
let(:champ) { described_class.new(master_value: 'tata', slave_value: 'tutu') } let(:champ) { described_class.new(primary_value: 'tata', secondary_value: 'tutu') }
before { champ.save } before { champ.save }

View file

@ -7,34 +7,34 @@ describe TypesDeChamp::LinkedDropDownListTypeDeChamp do
context 'with no options' do context 'with no options' do
let(:menu_options) { '' } let(:menu_options) { '' }
it { expect(type_de_champ.slave_options).to eq({}) } it { expect(type_de_champ.secondary_options).to eq({}) }
it { expect(type_de_champ.master_options).to eq([]) } it { expect(type_de_champ.primary_options).to eq([]) }
end end
context 'with two master options' do context 'with two primary options' do
let(:menu_options) do let(:menu_options) do
<<~END_OPTIONS <<~END_OPTIONS
--Master 1-- --Primary 1--
slave 1.1 secondary 1.1
slave 1.2 secondary 1.2
--Master 2-- --Primary 2--
slave 2.1 secondary 2.1
slave 2.2 secondary 2.2
slave 2.3 secondary 2.3
END_OPTIONS END_OPTIONS
end end
it do it do
expect(type_de_champ.slave_options).to eq( expect(type_de_champ.secondary_options).to eq(
{ {
'' => [], '' => [],
'Master 1' => [ '', 'slave 1.1', 'slave 1.2'], 'Primary 1' => [ '', 'secondary 1.1', 'secondary 1.2'],
'Master 2' => [ '', 'slave 2.1', 'slave 2.2', 'slave 2.3'] 'Primary 2' => [ '', 'secondary 2.1', 'secondary 2.2', 'secondary 2.3']
} }
) )
end end
it { expect(type_de_champ.master_options).to eq([ '', 'Master 1', 'Master 2' ]) } it { expect(type_de_champ.primary_options).to eq([ '', 'Primary 1', 'Primary 2' ]) }
end end
end end
end end