Skip to content

Commit

Permalink
Fix: Wrong logic in categories association with parents for upload/ed…
Browse files Browse the repository at this point in the history
…it forms (#906)

* add a method to convert categories with children list to categories with parents list

* pass categories with parents list to the parent categories selector stimulus controller

* fix the logic to distinguish between browse page, and upload/edit forms

* clean parents categories selector stimulus controller code to remove redendence

* add a comment to explain browse page logic and upload/edit forms logic in parent categories selector stimulus controller
  • Loading branch information
Bilelkihal authored Jan 10, 2025
1 parent b5989b0 commit db5694a
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 19 deletions.
10 changes: 10 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,16 @@ def categories_with_children(categories)
parent_to_children
end

def categories_with_parents(categories_children)
categories_parents = Hash.new { |hash, key| hash[key] = [] }
categories_children.each do |child, parents|
parents.each do |parent|
categories_parents[parent] << child
end
end
categories_parents
end

def id_to_acronym(id)
id.split('/').last
end
Expand Down
6 changes: 5 additions & 1 deletion app/helpers/submission_inputs_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,13 @@ def ontology_administered_by_input(ontology = @ontology, users_list = @user_sele
def ontology_categories_input(ontology = @ontology, categories = @categories)
categories ||= LinkedData::Client::Models::Category.all(display_links: false, display_context: false)
categories_children = categories_with_children(categories)
categories_parents = categories_with_parents(categories_children)

render Input::InputFieldComponent.new(name: '', label: 'Categories') do
content_tag(:div, class: 'upload-ontology-chips-container', 'data-controller': 'parent-categories-selector', 'data-parent-categories-selector-categories-children-value': "#{categories_children.to_json}", 'data-parent-categories-selector-target': "chips") do
content_tag(:div, class: 'upload-ontology-chips-container', 'data-controller': 'parent-categories-selector',
'data-parent-categories-selector-categories-children-value': "#{categories_children.to_json}",
'data-parent-categories-selector-categories-parents-value': "#{categories_parents.to_json}",
'data-parent-categories-selector-target': "chips") do
hidden_field_tag('ontology[hasDomain][]') +
categories.map do |category|
content_tag(:div, 'data-action': 'click->parent-categories-selector#check') do
Expand Down
58 changes: 40 additions & 18 deletions app/javascript/controllers/parent_categories_selector_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,50 @@ import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="parent-categories-selector"
export default class extends Controller {
static targets = ['chips']
static values = { categoriesChildren: Object}
static values = { categoriesChildren: Object, categoriesParents: Object}

check(event){
const input = event.currentTarget.querySelector('input')
const allInputs = this.chipsTarget.querySelectorAll('input')
const parents = this.categoriesChildrenValue
if(this.#id_to_acronym(input.value) in parents){
const parentChildren = parents[this.#id_to_acronym(input.value)]
allInputs.forEach(i => {
if(parentChildren.includes(this.#id_to_acronym(i.value))){
if(input.checked){
i.checked = true;
i.dispatchEvent(new Event('change', { bubbles: true }));
} else {
i.checked = false;
i.dispatchEvent(new Event('change', { bubbles: true }));
}
}
});
check(event) {
const input = event.currentTarget.querySelector('input');
const allInputs = this.chipsTarget.querySelectorAll('input');
const parents = this.categoriesChildrenValue;
const children = this.categoriesParentsValue;
const browseLogic = !this.hasCategoriesParentsValue;

// Browse page logic:
// - Selecting a category will auto select all its children
// - Deselecting a category will auto deselect all its children
// Upload/Edit forms logic:
// - Selecting a category will auto select its parents
// - Deselecting a category will auto deselect its children

const inputAcronym = this.#id_to_acronym(input.value);

if (browseLogic) {
if (inputAcronym in parents) {
const parentChildren = parents[inputAcronym];
this.#toggleInputState(allInputs, i => parentChildren.includes(this.#id_to_acronym(i.value)), input.checked);
}
} else {
if (inputAcronym in parents) {
const parentChildren = parents[inputAcronym];
this.#toggleInputState(allInputs, i => parentChildren.includes(this.#id_to_acronym(i.value)), false);
}
if (inputAcronym in children) {
const childParents = children[inputAcronym];
this.#toggleInputState(allInputs, i => childParents.includes(this.#id_to_acronym(i.value)), true);
}
}
}

#toggleInputState(inputs, condition, state) {
inputs.forEach(input => {
if (condition(input)) {
input.checked = state;
input.dispatchEvent(new Event('change', { bubbles: true }));
}
});
}

#id_to_acronym(id){
return id.split('/').pop();
}
Expand Down

0 comments on commit db5694a

Please sign in to comment.