Skip to content

Commit f1ecd13

Browse files
shiv-tyagiaceta-minophen
authored andcommitted
add method to check uncheck by category and improve dependency handling
Co-authored-by: Sukritee Sharma <[email protected]>
1 parent 6acba44 commit f1ecd13

File tree

1 file changed

+135
-65
lines changed

1 file changed

+135
-65
lines changed

static/js/add_build.js

Lines changed: 135 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,30 @@ const Features = (() => {
22
let features = {};
33
let defines_dictionary = {};
44
let labels_dictionary = {};
5+
let category_dictionary = {};
56

67
function resetDictionaries() {
7-
defines_dictionary = {}; // clear old dictionary
8-
labels_dictionary = {}; // clear old dictionary
8+
// clear old dictionaries
9+
defines_dictionary = {};
10+
labels_dictionary = {};
11+
category_dictionary = {};
12+
913
features.forEach((category) => {
14+
category_dictionary[category.name] = category;
1015
category['options'].forEach((option) => {
1116
defines_dictionary[option.define] = labels_dictionary[option.label] = option;
1217
});
1318
});
1419
}
1520

21+
function store_category_in_options() {
22+
features.forEach((category) => {
23+
category['options'].forEach((option) => {
24+
option.category_name = category.name;
25+
});
26+
});
27+
}
28+
1629
function updateRequiredFor() {
1730
features.forEach((category) => {
1831
category['options'].forEach((option) => {
@@ -33,6 +46,7 @@ const Features = (() => {
3346
features = new_features;
3447
resetDictionaries();
3548
updateRequiredFor();
49+
store_category_in_options();
3650
}
3751

3852
function getOptionByDefine(define) {
@@ -43,6 +57,14 @@ const Features = (() => {
4357
return labels_dictionary[label];
4458
}
4559

60+
function getCategoryByName(category_name) {
61+
return category_dictionary[category_name];
62+
}
63+
64+
function getCategoryIdByName(category_name) {
65+
return 'category_'+category_name.split(" ").join("_");
66+
}
67+
4668
function updateDefaults(defines_array) {
4769
// updates default on the basis of define array passed
4870
// the define array consists define in format, EXAMPLE_DEFINE or !EXAMPLE_DEFINE
@@ -56,13 +78,7 @@ const Features = (() => {
5678
}
5779
}
5880

59-
function fixDepencencyHelper(feature_label, visited) {
60-
if (visited[feature_label] != undefined ) {
61-
return;
62-
}
63-
64-
visited[feature_label] = true;
65-
document.getElementById(feature_label).checked = true;
81+
function enableDependenciesForFeature(feature_label) {
6682
let feature = getOptionByLabel(feature_label);
6783

6884
if (feature.dependency == null) {
@@ -71,34 +87,93 @@ const Features = (() => {
7187

7288
let children = feature.dependency.split(',');
7389
children.forEach((child) => {
74-
fixDepencencyHelper(child, visited);
90+
const check = true;
91+
checkUncheckOptionByLabel(child, check);
7592
});
7693
}
7794

78-
function fixAllDependencies() {
79-
var visited = {};
80-
Object.keys(labels_dictionary).forEach((label) => {
81-
if (document.getElementById(label).checked) {
82-
fixDepencencyHelper(label, visited);
95+
function handleOptionStateChange(feature_label, triggered_by_ui) {
96+
if (document.getElementById(feature_label).checked) {
97+
enableDependenciesForFeature(feature_label);
98+
} else {
99+
if (triggered_by_ui) {
100+
askToDisableDependentsForFeature(feature_label);
101+
} else {
102+
disabledDependentsForFeature(feature_label);
83103
}
104+
}
105+
106+
updateCategoryCheckboxState(getOptionByLabel(feature_label).category_name);
107+
}
108+
109+
function askToDisableDependentsForFeature(feature_label) {
110+
let enabled_dependent_features = getEnabledDependentFeaturesFor(feature_label);
111+
112+
if (enabled_dependent_features.length <= 0) {
113+
return;
114+
}
115+
116+
document.getElementById('modalBody').innerHTML = "The feature(s) <strong>"+enabled_dependent_features.join(", ")+"</strong> is/are dependant on <strong>"+feature_label+"</strong>" +
117+
" and hence will be disabled too.<br><strong>Do you want to continue?</strong>";
118+
document.getElementById('modalDisableButton').onclick = () => { disabledDependentsForFeature(feature_label); };
119+
document.getElementById('modalCancelButton').onclick = document.getElementById('modalCloseButton').onclick = () => {
120+
const check = true;
121+
checkUncheckOptionByLabel(feature_label, check);
122+
};
123+
var confirmationModal = bootstrap.Modal.getOrCreateInstance(document.getElementById('dependencyCheckModal'));
124+
confirmationModal.show();
125+
}
126+
127+
function disabledDependentsForFeature(feature_label) {
128+
let feature = getOptionByLabel(feature_label);
129+
130+
if (feature.requiredFor == undefined) {
131+
return;
132+
}
133+
134+
let dependents = feature.requiredFor;
135+
dependents.forEach((dependent) => {
136+
const check = false;
137+
checkUncheckOptionByLabel(dependent, false);
84138
});
85139
}
86140

87-
function handleDependenciesForFeature(feature_label) {
88-
var visited = {};
89-
if (document.getElementById(feature_label).checked) {
90-
fixDepencencyHelper(feature_label, visited);
91-
} else {
92-
enabled_dependent_features = getEnabledDependentFeaturesFor(feature_label);
93-
if (enabled_dependent_features.length > 0) {
94-
document.getElementById('modalBody').innerHTML = "The feature(s) <strong>"+enabled_dependent_features.join(", ")+"</strong> is/are dependant on <strong>"+feature_label+"</strong>" +
95-
" and hence will be disabled too.<br><strong>Do you want to continue?</strong>";
96-
document.getElementById('modalDisableButton').onclick = () => { disableCheckboxesByIds(enabled_dependent_features); }
97-
document.getElementById('modalCancelButton').onclick = document.getElementById('modalCloseButton').onclick = () => { document.getElementById(feature_label).checked = true; };
98-
var confirmationModal = bootstrap.Modal.getOrCreateInstance(document.getElementById('dependencyCheckModal'));
99-
confirmationModal.show();
141+
function updateCategoryCheckboxState(category_name) {
142+
let category = getCategoryByName(category_name);
143+
144+
if (category == undefined) {
145+
console.log("Could not find category by given name");
146+
}
147+
148+
let checked_options_count = 0;
149+
150+
category.options.forEach((option) => {
151+
let element = document.getElementById(option.label);
152+
153+
if (element && element.checked) {
154+
checked_options_count += 1;
100155
}
156+
});
157+
158+
let category_checkbox_element = document.getElementById(getCategoryIdByName(category_name));
159+
if (category_checkbox_element == undefined) {
160+
console.log("Could not find element for given category");
161+
}
162+
163+
let indeterminate_state = false;
164+
switch(checked_options_count) {
165+
case 0:
166+
category_checkbox_element.checked = false;
167+
break;
168+
case category.options.length:
169+
category_checkbox_element.checked = true;
170+
break;
171+
default:
172+
indeterminate_state = true;
173+
break;
101174
}
175+
176+
category_checkbox_element.indeterminate = indeterminate_state;
102177
}
103178

104179
function getEnabledDependentFeaturesHelper(feature_label, visited, dependent_features) {
@@ -132,40 +207,38 @@ const Features = (() => {
132207
return dependent_features;
133208
}
134209

135-
function disableDependents(feature_label) {
136-
if (getOptionByLabel(feature_label).requiredFor == undefined) {
137-
return;
138-
}
139-
140-
getOptionByLabel(feature_label).requiredFor.forEach((dependent_feature) => {
141-
document.getElementById(dependent_feature).checked = false;
142-
});
143-
}
144-
145210
function applyDefaults() {
146211
features.forEach(category => {
147212
category['options'].forEach(option => {
148-
element = document.getElementById(option['label']);
149-
if (element != undefined) {
150-
element.checked = (option['default'] == 1);
151-
}
213+
const check = option['default'] == 1;
214+
checkUncheckOptionByLabel(option.label, check);
152215
});
153216
});
154-
fixAllDependencies();
217+
}
218+
219+
function checkUncheckOptionByLabel(label, check) {
220+
let element = document.getElementById(label);
221+
if (element == undefined || element.checked == check) {
222+
return;
223+
}
224+
element.checked = check;
225+
const triggered_by_ui = false;
226+
handleOptionStateChange(label, triggered_by_ui);
155227
}
156228

157229
function checkUncheckAll(check) {
158230
features.forEach(category => {
159-
category['options'].forEach(option => {
160-
element = document.getElementById(option['label']);
161-
if (element != undefined) {
162-
element.checked = check;
163-
}
164-
});
231+
checkUncheckCategory(category.name, check);
165232
});
166233
}
167234

168-
return {reset, handleDependenciesForFeature, disableDependents, updateDefaults, applyDefaults, checkUncheckAll};
235+
function checkUncheckCategory(category_name, check) {
236+
getCategoryByName(category_name).options.forEach(option => {
237+
checkUncheckOptionByLabel(option.label, check);
238+
});
239+
}
240+
241+
return {reset, handleOptionStateChange, getCategoryIdByName, updateDefaults, applyDefaults, checkUncheckAll, checkUncheckCategory};
169242
})();
170243

171244
var init_categories_expanded = false;
@@ -200,15 +273,6 @@ function setSpinnerToDiv(id, message) {
200273
}
201274
}
202275

203-
function disableCheckboxesByIds(ids) {
204-
ids.forEach((id) => {
205-
box_element = document.getElementById(id);
206-
if (box_element) {
207-
box_element.checked = false;
208-
}
209-
})
210-
}
211-
212276
function onVehicleChange(new_vehicle) {
213277
// following elemets will be blocked (disabled) when we make the request
214278
let elements_to_block = ['vehicle', 'branch', 'board', 'submit', 'reset_def', 'exp_col_button'];
@@ -359,20 +423,25 @@ function createCategoryCard(category_name, options, expanded) {
359423
options_html = "";
360424
options.forEach(option => {
361425
options_html += '<div class="form-check">' +
362-
'<input class="form-check-input" type="checkbox" value="1" name="'+option['label']+'" id="'+option['label']+'" onclick="Features.handleDependenciesForFeature(this.id);">' +
363-
'<label class="form-check-label" for="'+option['label']+'">' +
426+
'<input class="form-check-input" type="checkbox" value="1" name="'+option['label']+'" id="'+option['label']+'" onclick="Features.handleOptionStateChange(this.id, true);">' +
427+
'<label class="form-check-label ms-2" for="'+option['label']+'">' +
364428
option['description'].replace(/enable/i, "") +
365429
'</label>' +
366430
'</div>';
367431
});
368432

369-
let id_prefix = category_name.split(" ").join("_");
433+
let id_prefix = Features.getCategoryIdByName(category_name);
370434
let card_element = document.createElement('div');
371435
card_element.setAttribute('class', 'card ' + (expanded == true ? 'h-100' : ''));
372436
card_element.id = id_prefix + '_card';
373-
card_element.innerHTML = '<div class="card-header">' +
437+
card_element.innerHTML = '<div class="card-header ps-3">' +
374438
'<div class="d-flex justify-content-between">' +
375-
'<span class="d-flex align-items-center"><strong>'+category_name+'</strong></span>' +
439+
'<div class="d-inline-flex">' +
440+
'<span class="align-middle me-3"><input class="form-check-input" type="checkbox" id="'+Features.getCategoryIdByName(category_name)+'" onclick="Features.checkUncheckCategory(\''+category_name+'\', this.checked);"></span>' +
441+
'<strong>' +
442+
'<label for="check-uncheck-category">' + category_name + '</label>' +
443+
'</strong>' +
444+
'</div>' +
376445
'<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#'+id_prefix+'_collapse" aria-expanded="false" aria-controls="'+id_prefix+'_collapse">' +
377446
'<i class="bi bi-chevron-'+(expanded == true ? 'up' : 'down')+'" id="'+id_prefix+'_icon'+'"></i>' +
378447
'</button>' +
@@ -381,7 +450,7 @@ function createCategoryCard(category_name, options, expanded) {
381450
let collapse_element = document.createElement('div');
382451
collapse_element.setAttribute('class', 'feature-group collapse '+(expanded == true ? 'show' : ''));
383452
collapse_element.id = id_prefix + '_collapse';
384-
collapse_element.innerHTML = '<div class="container-fluid px-2 py-2">'+options_html+'</div>';
453+
collapse_element.innerHTML = '<div class="container-fluid px-3 py-2">'+options_html+'</div>';
385454
card_element.appendChild(collapse_element);
386455

387456
// add relevent event listeners
@@ -393,6 +462,7 @@ function createCategoryCard(category_name, options, expanded) {
393462
card_element.classList.add('h-100');
394463
document.getElementById(id_prefix+'_icon').setAttribute('class', 'bi bi-chevron-up');
395464
});
465+
396466
return card_element;
397467
}
398468

0 commit comments

Comments
 (0)