157 lines
5.5 KiB
JavaScript
157 lines
5.5 KiB
JavaScript
/**
|
|
* Dynamic filtering for OperationTemplate admin form
|
|
* Updates categories based on thematic selection
|
|
* Updates asset models based on categories selection
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
function initDynamicFiltering() {
|
|
if (typeof django === 'undefined' || typeof django.jQuery === 'undefined') {
|
|
// Retry shortly if Django's bundled jQuery is not yet present
|
|
setTimeout(initDynamicFiltering, 100);
|
|
return;
|
|
}
|
|
|
|
var $ = django.jQuery;
|
|
|
|
$(document).ready(function() {
|
|
var $thematic = $('#id_thematic');
|
|
var $categoriesFrom = $('#id_categories_from');
|
|
var $categoriesTo = $('#id_categories_to');
|
|
var $assetModelsFrom = $('#id_asset_models_from');
|
|
var $assetModelsTo = $('#id_asset_models_to');
|
|
|
|
if (!$thematic.length) return;
|
|
|
|
/**
|
|
* Update categories based on selected thematic
|
|
*/
|
|
function updateCategories() {
|
|
var thematicId = $thematic.val();
|
|
|
|
if (!thematicId) {
|
|
// Clear categories if no thematic selected
|
|
$categoriesFrom.empty();
|
|
$categoriesTo.empty();
|
|
updateAssetModels();
|
|
return;
|
|
}
|
|
|
|
// Get current selections
|
|
var selectedCategories = $categoriesTo.find('option').map(function() {
|
|
return $(this).val();
|
|
}).get();
|
|
|
|
// Fetch filtered categories
|
|
$.ajax({
|
|
url: '/interventions/ajax/get-categories-by-thematic/',
|
|
data: { thematic_id: thematicId },
|
|
success: function(data) {
|
|
// Clear both lists
|
|
$categoriesFrom.empty();
|
|
$categoriesTo.empty();
|
|
|
|
// Populate categories
|
|
data.categories.forEach(function(cat) {
|
|
var option = $('<option></option>')
|
|
.val(cat.id)
|
|
.text(cat.name);
|
|
|
|
// If previously selected, add to "chosen" list
|
|
if (selectedCategories.indexOf(String(cat.id)) !== -1) {
|
|
$categoriesTo.append(option);
|
|
} else {
|
|
$categoriesFrom.append(option);
|
|
}
|
|
});
|
|
|
|
// Update asset models after categories change
|
|
updateAssetModels();
|
|
},
|
|
error: function() {
|
|
console.error('Error fetching categories');
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Update asset models based on selected categories (or thematic if no categories)
|
|
*/
|
|
function updateAssetModels() {
|
|
var thematicId = $thematic.val();
|
|
var categoryIds = $categoriesTo.find('option').map(function() {
|
|
return $(this).val();
|
|
}).get();
|
|
|
|
if (!thematicId) {
|
|
// Clear asset models if no thematic selected
|
|
$assetModelsFrom.empty();
|
|
$assetModelsTo.empty();
|
|
return;
|
|
}
|
|
|
|
// Get current selections
|
|
var selectedModels = $assetModelsTo.find('option').map(function() {
|
|
return $(this).val();
|
|
}).get();
|
|
|
|
// Fetch filtered asset models
|
|
$.ajax({
|
|
url: '/interventions/ajax/get-asset-models/',
|
|
data: {
|
|
thematic_id: thematicId,
|
|
category_ids: categoryIds.join(',')
|
|
},
|
|
success: function(data) {
|
|
// Clear both lists
|
|
$assetModelsFrom.empty();
|
|
$assetModelsTo.empty();
|
|
|
|
// Populate asset models
|
|
data.models.forEach(function(model) {
|
|
var option = $('<option></option>')
|
|
.val(model.value)
|
|
.text(model.display);
|
|
|
|
// If previously selected, add to "chosen" list
|
|
if (selectedModels.indexOf(model.value) !== -1) {
|
|
$assetModelsTo.append(option);
|
|
} else {
|
|
$assetModelsFrom.append(option);
|
|
}
|
|
});
|
|
},
|
|
error: function() {
|
|
console.error('Error fetching asset models');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Listen to thematic changes
|
|
$thematic.on('change', function() {
|
|
updateCategories();
|
|
});
|
|
|
|
// Listen to categories changes using MutationObserver
|
|
// (filter_horizontal uses JavaScript to move options, not change events)
|
|
if ($categoriesTo.length) {
|
|
var observer = new MutationObserver(function(mutations) {
|
|
updateAssetModels();
|
|
});
|
|
|
|
observer.observe($categoriesTo[0], {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Start initialization
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initDynamicFiltering);
|
|
} else {
|
|
initDynamicFiltering();
|
|
}
|
|
})();
|