js_tree_element_improvement #161
@ -65,24 +65,23 @@ class KonovaCode(models.Model):
|
|||||||
ret_val += ", " + self.parent.long_name
|
ret_val += ", " + self.parent.long_name
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def add_children(self):
|
def add_children(self, order_by: str = "long_name"):
|
||||||
""" Adds all children (resurcively until leaf) as .children to the KonovaCode
|
""" Adds all children (resurcively until leaf) as .children to the KonovaCode
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
code (KonovaCode): The manipulated KonovaCode instance
|
code (KonovaCode): The manipulated KonovaCode instance
|
||||||
"""
|
"""
|
||||||
if self.is_leaf:
|
if self.is_leaf:
|
||||||
return None
|
return self
|
||||||
|
|
||||||
children = KonovaCode.objects.filter(
|
children = KonovaCode.objects.filter(
|
||||||
code_lists__in=self.code_lists.all(),
|
|
||||||
parent=self
|
parent=self
|
||||||
).order_by(
|
).order_by(
|
||||||
"long_name"
|
order_by
|
||||||
)
|
)
|
||||||
self.children = children
|
self.children = children
|
||||||
for child in children:
|
for child in children:
|
||||||
child.add_children()
|
child.add_children(order_by)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ from codelist.models import KonovaCode
|
|||||||
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
|
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
|
||||||
CODELIST_COMPENSATION_ACTION_DETAIL_ID
|
CODELIST_COMPENSATION_ACTION_DETAIL_ID
|
||||||
from compensation.models import CompensationDocument, EcoAccountDocument
|
from compensation.models import CompensationDocument, EcoAccountDocument
|
||||||
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
|
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple, \
|
||||||
|
CompensationStateTreeRadioSelect
|
||||||
from konova.contexts import BaseContext
|
from konova.contexts import BaseContext
|
||||||
from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
|
from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
|
||||||
from konova.models import DeadlineType
|
from konova.models import DeadlineType
|
||||||
@ -156,22 +157,12 @@ class NewStateModalForm(BaseModalForm):
|
|||||||
What has been on this area before changes/compensations have been applied and what will be the result ('after')?
|
What has been on this area before changes/compensations have been applied and what will be the result ('after')?
|
||||||
|
|
||||||
"""
|
"""
|
||||||
biotope_type = forms.ModelChoiceField(
|
biotope_type = forms.MultipleChoiceField(
|
||||||
label=_("Biotope Type"),
|
label=_("Biotope Type"),
|
||||||
label_suffix="",
|
label_suffix="",
|
||||||
required=True,
|
required=True,
|
||||||
help_text=_("Select the biotope type"),
|
help_text=_("Select the biotope type"),
|
||||||
queryset=KonovaCode.objects.filter(
|
widget=CompensationStateTreeRadioSelect(),
|
||||||
is_archived=False,
|
|
||||||
is_leaf=True,
|
|
||||||
code_lists__in=[CODELIST_BIOTOPES_ID],
|
|
||||||
),
|
|
||||||
widget=autocomplete.ModelSelect2(
|
|
||||||
url="codes-biotope-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Biotope Type"),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
biotope_extra = forms.ModelMultipleChoiceField(
|
biotope_extra = forms.ModelMultipleChoiceField(
|
||||||
label=_("Biotope additional type"),
|
label=_("Biotope additional type"),
|
||||||
@ -272,7 +263,7 @@ class EditCompensationStateModalForm(NewStateModalForm):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.form_title = _("Edit state")
|
self.form_title = _("Edit state")
|
||||||
form_data = {
|
form_data = {
|
||||||
"biotope_type": self.state.biotope_type,
|
"biotope_type": self.state.biotope_type.id,
|
||||||
"biotope_extra": self.state.biotope_type_details.all(),
|
"biotope_extra": self.state.biotope_type_details.all(),
|
||||||
"surface": self.state.surface,
|
"surface": self.state.surface,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from codelist.models import KonovaCode
|
from codelist.models import KonovaCode
|
||||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID
|
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID
|
||||||
|
|
||||||
|
|
||||||
class DummyFilterInput(forms.HiddenInput):
|
class DummyFilterInput(forms.HiddenInput):
|
||||||
@ -38,7 +38,17 @@ class TreeCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
|
|||||||
""" Provides multiple selection of parent-child data
|
""" Provides multiple selection of parent-child data
|
||||||
|
|
||||||
"""
|
"""
|
||||||
template_name = "konova/widgets/checkbox-tree-select.html"
|
template_name = "konova/widgets/tree/checkbox/checkbox-tree-select.html"
|
||||||
|
|
||||||
|
class meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class TreeRadioSelect(forms.RadioSelect):
|
||||||
|
""" Provides single selection of parent-child data
|
||||||
|
|
||||||
|
"""
|
||||||
|
template_name = "konova/widgets/tree/radio/radio-tree-select.html"
|
||||||
|
|
||||||
class meta:
|
class meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
@ -68,6 +78,30 @@ class KonovaCodeTreeCheckboxSelectMultiple(TreeCheckboxSelectMultiple):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
class KonovaCodeTreeRadioSelect(TreeRadioSelect):
|
||||||
|
""" Provides single selection of KonovaCode
|
||||||
|
|
||||||
|
"""
|
||||||
|
filter = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.code_list = kwargs.pop("code_list", None)
|
||||||
|
self.filter = kwargs.pop("filter", {})
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_context(self, name, value, attrs):
|
||||||
|
context = super().get_context(name, value, attrs)
|
||||||
|
codes = KonovaCode.objects.filter(
|
||||||
|
**self.filter,
|
||||||
|
)
|
||||||
|
codes = [
|
||||||
|
parent_code.add_children()
|
||||||
|
for parent_code in codes
|
||||||
|
]
|
||||||
|
context["codes"] = codes
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectMultiple):
|
class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectMultiple):
|
||||||
""" Provides multiple selection of CompensationActions
|
""" Provides multiple selection of CompensationActions
|
||||||
|
|
||||||
@ -79,4 +113,31 @@ class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectM
|
|||||||
self.filter = {
|
self.filter = {
|
||||||
"code_lists__in": [CODELIST_COMPENSATION_ACTION_ID],
|
"code_lists__in": [CODELIST_COMPENSATION_ACTION_ID],
|
||||||
"parent": None,
|
"parent": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CompensationStateTreeRadioSelect(KonovaCodeTreeRadioSelect):
|
||||||
|
""" Provides single selection of CompensationState
|
||||||
|
|
||||||
|
"""
|
||||||
|
filter = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.filter = {
|
||||||
|
"code_lists__in": [CODELIST_BIOTOPES_ID],
|
||||||
|
"parent": None,
|
||||||
|
"is_archived": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_context(self, name, value, attrs):
|
||||||
|
context = super().get_context(name, value, attrs)
|
||||||
|
codes = KonovaCode.objects.filter(
|
||||||
|
**self.filter,
|
||||||
|
)
|
||||||
|
codes = [
|
||||||
|
parent_code.add_children("short_name")
|
||||||
|
for parent_code in codes
|
||||||
|
]
|
||||||
|
context["codes"] = codes
|
||||||
|
return context
|
@ -10,12 +10,15 @@
|
|||||||
{% fa5_icon 'angle-down' %}
|
{% fa5_icon 'angle-down' %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if code.short_name %}
|
||||||
|
({{code.short_name}})
|
||||||
|
{% endif %}
|
||||||
{{code.long_name}}
|
{{code.long_name}}
|
||||||
</label>
|
</label>
|
||||||
{% if not code.is_leaf %}
|
{% if not code.is_leaf %}
|
||||||
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
|
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
|
||||||
{% with code.children as codes %}
|
{% with code.children as codes %}
|
||||||
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
|
{% include 'konova/widgets/tree/checkbox/checkbox-tree-select-content.html' %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
@ -5,7 +5,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="tree-root">
|
<div id="tree-root">
|
||||||
{% include 'konova/widgets/checkbox-tree-select-content.html' %}
|
{% include 'konova/widgets/tree/checkbox/checkbox-tree-select-content.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
@ -0,0 +1,25 @@
|
|||||||
|
{% load l10n fontawesome_5 %}
|
||||||
|
{% for code in codes %}
|
||||||
|
<div class="ml-4 tree-element">
|
||||||
|
<label class="tree-label collapsed" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
|
||||||
|
{% if code.is_leaf%}
|
||||||
|
<input class="tree-input" id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="radio" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
|
||||||
|
{% else %}
|
||||||
|
<span class="collapse-icn">
|
||||||
|
{% fa5_icon 'angle-down' %}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if code.short_name %}
|
||||||
|
({{code.short_name}})
|
||||||
|
{% endif %}
|
||||||
|
{{code.long_name}}
|
||||||
|
</label>
|
||||||
|
{% if not code.is_leaf %}
|
||||||
|
<div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
|
||||||
|
{% with code.children as codes %}
|
||||||
|
{% include 'konova/widgets/tree/radio/radio-tree-select-content.html' %}
|
||||||
|
{% endwith %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
@ -0,0 +1,70 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="ml-4 mb-4">
|
||||||
|
<input id="tree-search-input" class="form-control" type="text" placeholder="{% trans 'Search' %}"/>
|
||||||
|
</div>
|
||||||
|
<div id="tree-root">
|
||||||
|
{% include 'konova/widgets/tree/radio/radio-tree-select-content.html' %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSelectedCssClass(element){
|
||||||
|
element = $(element);
|
||||||
|
var cssClass = "badge rlp-r"
|
||||||
|
|
||||||
|
var directParent = element.closest(".tree-element-children")
|
||||||
|
var root = element.parents(".tree-element-children")
|
||||||
|
|
||||||
|
var otherCheckedInputsOfParent = directParent.find('.tree-input:checked');
|
||||||
|
var otherCheckedInputsOfRoot = root.find('.tree-input:checked');
|
||||||
|
|
||||||
|
if(otherCheckedInputsOfParent.length == 0){
|
||||||
|
var parentLabel = directParent.siblings(".tree-label");
|
||||||
|
parentLabel.removeClass(cssClass)
|
||||||
|
if(otherCheckedInputsOfRoot.length == 0){
|
||||||
|
var rootLabel = root.siblings(".tree-label")
|
||||||
|
rootLabel.removeClass(cssClass)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var rootAndParentLabel = root.siblings(".tree-label");
|
||||||
|
rootAndParentLabel.addClass(cssClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeHandler(event){
|
||||||
|
toggleSelectedCssClass(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchInputHandler(event){
|
||||||
|
var elem = $(this);
|
||||||
|
var val = elem.val()
|
||||||
|
var allTreeElements = $(".tree-element")
|
||||||
|
var allTreeElementsContain = $(".tree-element").filter(function(){
|
||||||
|
var reg = new RegExp(val, "i");
|
||||||
|
return reg.test($(this).text());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if(val.length > 0){
|
||||||
|
// Hide everything
|
||||||
|
allTreeElements.hide()
|
||||||
|
// Now show again everything matching the query
|
||||||
|
allTreeElementsContain.show()
|
||||||
|
}else{
|
||||||
|
// Show everything if no query exists
|
||||||
|
allTreeElements.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener on search input
|
||||||
|
$("#tree-search-input").keyup(searchInputHandler)
|
||||||
|
|
||||||
|
// Add event listener on changed checkboxes
|
||||||
|
$(".tree-input").change(changeHandler);
|
||||||
|
|
||||||
|
// initialize all pre-checked checkboxes (e.g. on an edit form)
|
||||||
|
var preCheckedElements = $(".tree-input:checked");
|
||||||
|
preCheckedElements.each(function (index, element){
|
||||||
|
toggleSelectedCssClass(element);
|
||||||
|
})
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user