Enhance LLM import preview with detailed M2M field handling and improved exclusion toggle functionality

This commit is contained in:
Ross
2025-10-20 11:54:12 +01:00
parent 16387fff77
commit c577da4779
+129 -24
View File
@@ -34,22 +34,100 @@
</p>
<p><strong>Feedback:</strong> {{ item.payload.feedback|default:''|safe }}</p>
{% endif %}
<p><strong>Missing M2M:</strong>
{% if item.missing_m2m %}
<ul>
{% for m in item.missing_m2m %}
<li>
{{ m.model }}:
{% for val in m.values %}
<button type="button" class="btn btn-sm btn-outline-danger ms-1 toggle-exclude" data-idx="{{ item.index }}" data-model="{{ m.model }}" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
</li>
<p><strong>M2M fields (click to exclude)</strong></p>
<p class="small text-muted">Green = will be created/attached. Click a value to exclude it (grey).</p>
<div class="mb-2">
<!-- Finding -->
<div class="m2m-group" data-model="Finding"><strong>Finding:</strong>
{% if item.resolved_m2m.finding %}
{% for val in item.resolved_m2m.finding %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Finding" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
</ul>
{% else %}
None
{% endif %}
</p>
{% endif %}
{% if item.missing_map.Finding %}
{% for val in item.missing_map.Finding %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Finding" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
<span class="text-muted m2m-none" style="display:none">(none)</span>
{% if item.missing_map.Finding %}
<div class="small text-info">Would create: {{ item.missing_map.Finding|join:", " }}</div>
{% endif %}
</div>
</div>
<!-- Structure -->
<div class="m2m-group" data-model="Structure"><strong>Structure:</strong>
{% if item.resolved_m2m.structure %}
{% for val in item.resolved_m2m.structure %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Structure" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
{% if item.missing_map.Structure %}
{% for val in item.missing_map.Structure %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Structure" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
<span class="text-muted m2m-none" style="display:none">(none)</span>
{% if item.missing_map.Structure %}
<div class="small text-info">Would create: {{ item.missing_map.Structure|join:", " }}</div>
{% endif %}
</div>
<!-- Condition -->
<div class="m2m-group" data-model="Condition"><strong>Condition:</strong>
{% if item.resolved_m2m.condition %}
{% for val in item.resolved_m2m.condition %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Condition" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
{% if item.missing_map.Condition %}
{% for val in item.missing_map.Condition %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Condition" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
<span class="text-muted m2m-none" style="display:none">(none)</span>
{% if item.missing_map.Condition %}
<div class="small text-info">Would create: {{ item.missing_map.Condition|join:", " }}</div>
{% endif %}
</div>
<!-- Presentation -->
<div class="m2m-group" data-model="Presentation"><strong>Presentation:</strong>
{% if item.resolved_m2m.presentation %}
{% for val in item.resolved_m2m.presentation %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Presentation" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
{% if item.missing_map.Presentation %}
{% for val in item.missing_map.Presentation %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Presentation" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
<span class="text-muted m2m-none" style="display:none">(none)</span>
{% if item.missing_map.Presentation %}
<div class="small text-info">Would create: {{ item.missing_map.Presentation|join:", " }}</div>
{% endif %}
</div>
<!-- Subspecialty -->
<div class="m2m-group" data-model="Subspecialty"><strong>Subspecialty:</strong>
{% if item.resolved_m2m.subspecialty %}
{% for val in item.resolved_m2m.subspecialty %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Subspecialty" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
{% if item.missing_map.Subspecialty %}
{% for val in item.missing_map.Subspecialty %}
<button type="button" class="m2m-toggle btn btn-sm btn-success ms-1" data-idx="{{ item.index }}" data-model="Subspecialty" data-value="{{ val }}">{{ val }}</button>
{% endfor %}
{% endif %}
<span class="text-muted m2m-none" style="display:none">(none)</span>
{% if item.missing_map.Subspecialty %}
<div class="small text-info">Would create: {{ item.missing_map.Subspecialty|join:", " }}</div>
{% endif %}
</div>
</div>
<div>
<label><input type="checkbox" name="selected" value="{{ item.index }}" checked> Include</label>
</div>
@@ -68,8 +146,8 @@
</form>
<script>
// Toggle exclude: clicking a missing M2M button will add/remove a hidden input
document.querySelectorAll('.toggle-exclude').forEach(function(btn){
// Toggle exclude: clicking a M2M button will add/remove a hidden input and update styles
function setupToggle(btn){
btn.addEventListener('click', function(){
const idx = btn.dataset.idx;
const model = btn.dataset.model;
@@ -77,12 +155,14 @@
const container = document.getElementById('exclude-container-' + idx);
const inputName = 'exclude_' + idx;
// check if an input for this value already exists
const existing = container.querySelector('input[data-model="' + model + '"][data-value="' + value + '"]');
const selector = 'input[data-model="' + model + '"][data-value="' + value + '"]';
const existing = container ? container.querySelector(selector) : null;
if(existing){
// remove input and toggle style
// remove input and toggle style to outline
existing.remove();
btn.classList.remove('btn-danger');
btn.classList.add('btn-outline-danger');
btn.classList.remove('btn-outline-secondary');
btn.classList.remove('btn-secondary');
btn.classList.add('btn-success');
} else {
const inp = document.createElement('input');
inp.type = 'hidden';
@@ -91,11 +171,36 @@
inp.setAttribute('data-model', model);
inp.setAttribute('data-value', value);
container.appendChild(inp);
btn.classList.remove('btn-outline-danger');
btn.classList.add('btn-danger');
// set button to excluded appearance
btn.classList.remove('btn-success');
btn.classList.add('btn-outline-secondary');
}
});
});
}
document.querySelectorAll('.m2m-toggle').forEach(setupToggle);
// keep backward compatibility with older toggle-exclude class
document.querySelectorAll('.toggle-exclude').forEach(setupToggle);
// Show '(none)' for empty groups
function refreshEmptyPlaceholders(){
document.querySelectorAll('.m2m-group').forEach(function(group){
const buttons = group.querySelectorAll('.m2m-toggle');
const none = group.querySelector('.m2m-none');
if(!none) return;
if(buttons.length === 0){
none.style.display = '';
} else {
none.style.display = 'none';
}
});
}
// run on load
refreshEmptyPlaceholders();
// when toggling, buttons are not removed from DOM, so no need to re-run on click;
// however if you later add server-side mutation that rewrites the fragment, call refreshEmptyPlaceholders after update.
</script>
<!-- Bottom controls removed: submit and cancel are inside the form above -->