[UPDT] HORILLA VIEWS: Generic solution to add addtional data along with dynamic create fields and fix group by action column width to default width
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from horilla_views.models import ActiveGroup, ActiveTab, ToggleColumn
|
||||
from horilla_views.models import ActiveGroup, ActiveTab, SavedFilter, ToggleColumn
|
||||
|
||||
admin.site.register([ToggleColumn, ActiveTab, ActiveGroup])
|
||||
|
||||
@@ -30,7 +30,6 @@ from django.utils.html import format_html
|
||||
from django.utils.safestring import SafeString
|
||||
from django.utils.translation import gettext_lazy as _trans
|
||||
|
||||
from base.methods import eval_validate
|
||||
from horilla import settings
|
||||
from horilla.horilla_middlewares import _thread_locals
|
||||
from horilla_views.templatetags.generic_template_filters import getattribute
|
||||
@@ -473,6 +472,8 @@ def value_to_field(field: object, value: list) -> Any:
|
||||
"""
|
||||
return value according to the format of the field
|
||||
"""
|
||||
from base.methods import eval_validate
|
||||
|
||||
if isinstance(field, models.ManyToManyField):
|
||||
return [int(val) for val in value]
|
||||
elif isinstance(
|
||||
|
||||
@@ -294,13 +294,14 @@ class HorillaListView(ListView):
|
||||
keys_to_remove = [
|
||||
key
|
||||
for key, value in data_dict.items()
|
||||
if value[0] in ["unknown", "on"] + self.filter_keys_to_remove
|
||||
if key in ["filter_applied", "nav_url"] + self.filter_keys_to_remove
|
||||
]
|
||||
|
||||
for key in keys_to_remove + ["referrer"]:
|
||||
if key in data_dict.keys():
|
||||
data_dict.pop(key)
|
||||
context["filter_dict"] = data_dict
|
||||
context["keys_to_remove"] = keys_to_remove
|
||||
|
||||
request = self.request
|
||||
ordered_ids = list(queryset.values_list("id", flat=True))
|
||||
@@ -813,6 +814,8 @@ class HorillaFormView(FormView):
|
||||
|
||||
# NOTE: Dynamic create view's forms save method will be overwritten
|
||||
is_dynamic_create_view: bool = False
|
||||
# [(field_name,DynamicFormView,[other_field1,...])] # other_fields
|
||||
# can be mentioned like this to pass the field selected
|
||||
dynamic_create_fields: list = []
|
||||
|
||||
def __init__(self, **kwargs: Any) -> None:
|
||||
@@ -903,7 +906,10 @@ class HorillaFormView(FormView):
|
||||
files = self.request.FILES
|
||||
form = self.init_form(data=data, files=files, instance=instance)
|
||||
if self.is_dynamic_create_view:
|
||||
setattr(type(form), "save", save)
|
||||
# setattr(type(form), "save", save)
|
||||
from types import MethodType
|
||||
|
||||
form.save = MethodType(save, form)
|
||||
|
||||
if self.request.method == "GET":
|
||||
[
|
||||
@@ -916,6 +922,9 @@ class HorillaFormView(FormView):
|
||||
view = dynamic_tuple[1]
|
||||
view.display_title = "Dynamic create"
|
||||
field = dynamic_tuple[0]
|
||||
additional_data_fields = []
|
||||
if len(dynamic_tuple) == 3:
|
||||
additional_data_fields = dynamic_tuple[2]
|
||||
key = self.request.session.session_key + "cbv" + field
|
||||
field_instance = form.instance._meta.get_field(field)
|
||||
value = form.initial.get(field, [])
|
||||
@@ -931,7 +940,6 @@ class HorillaFormView(FormView):
|
||||
)
|
||||
else:
|
||||
value = getattr(getattribute(form.instance, field), "pk", value)
|
||||
|
||||
CACHE.set(
|
||||
key,
|
||||
{
|
||||
@@ -957,6 +965,22 @@ class HorillaFormView(FormView):
|
||||
choices.insert(0, ("", "Select option"))
|
||||
choices.append(("dynamic_create", "Dynamic create"))
|
||||
attrs = form.fields[field].widget.attrs
|
||||
for data_field in additional_data_fields:
|
||||
|
||||
data_field_attr = form.fields[data_field].widget.attrs
|
||||
if (
|
||||
f"$('#modalButton{field}Form [name={data_field}]').val(this.value);"
|
||||
not in data_field_attr.get("onchange", "")
|
||||
):
|
||||
data_field_attr["onchange"] = (
|
||||
data_field_attr.get("onchange", "")
|
||||
+ f"""
|
||||
if(this.value != 'dynamic_create'){{
|
||||
$('#modalButton{field}Form [name={data_field}]').val(this.value);
|
||||
}}
|
||||
"""
|
||||
)
|
||||
|
||||
form.fields[field] = form_field(
|
||||
choices=choices,
|
||||
label=form.fields[field].label,
|
||||
@@ -967,6 +991,18 @@ class HorillaFormView(FormView):
|
||||
)
|
||||
form.fields[field].widget.attrs = attrs
|
||||
form.initial[field] = value
|
||||
for dynamic_tuple in self.dynamic_create_fields:
|
||||
field = dynamic_tuple[0]
|
||||
onchange = form.fields[field].widget.attrs.get("onchange", "")
|
||||
if onchange:
|
||||
CACHE.set(
|
||||
self.request.session.session_key
|
||||
+ "cbv"
|
||||
+ field
|
||||
+ "onchange",
|
||||
onchange,
|
||||
)
|
||||
|
||||
if pk:
|
||||
form.instance = instance
|
||||
title = str(instance)
|
||||
@@ -1004,6 +1040,7 @@ class HorillaNavView(TemplateView):
|
||||
filter_instance: FilterSet = None
|
||||
filter_instance_context_name: str = ""
|
||||
filter_body_template: str = ""
|
||||
empty_inputs: list = []
|
||||
view_types: list = []
|
||||
create_attrs: str = """"""
|
||||
|
||||
@@ -1027,8 +1064,12 @@ class HorillaNavView(TemplateView):
|
||||
context["search_in"] = self.search_in
|
||||
context["filter_instance_context_name"] = self.filter_instance
|
||||
last_filter = CACHE.get(
|
||||
self.request.session.session_key + "last-applied-filter", {}
|
||||
self.request.session.session_key
|
||||
+ "last-applied-filter"
|
||||
+ self.request.path,
|
||||
{},
|
||||
)
|
||||
context["empty_inputs"] = self.empty_inputs + ["nav_url"]
|
||||
context["last_filter"] = dict(last_filter)
|
||||
if self.filter_instance:
|
||||
context[self.filter_form_context_name] = self.filter_instance.form
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
<div style="display: none">{{filter_dict}}</div>
|
||||
<script>
|
||||
function fieldLabel(value, field) {
|
||||
if ({{keys_to_remove|safe}}.includes(field)) {
|
||||
return ""
|
||||
}
|
||||
fiedlElem = $(`#applyFilter`).closest(`form`).find(`[name=${field}]`);
|
||||
if (fiedlElem.is("select")) {
|
||||
// my conditions
|
||||
|
||||
@@ -216,10 +216,12 @@
|
||||
</table>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
attrAction =`{{header_attrs.action|safe}}`
|
||||
if (!attrAction){
|
||||
let thWidth = 0;
|
||||
const widths = [];
|
||||
|
||||
$('.lastTd').each(function () {
|
||||
$('#{{view_id}} .lastTd').each(function () {
|
||||
widths.push(this.scrollWidth);
|
||||
$(this).css('overflow', 'hidden');
|
||||
});
|
||||
@@ -229,8 +231,12 @@
|
||||
if (widths.length) {
|
||||
thWidth = widths[0];
|
||||
}
|
||||
if (!thWidth) {
|
||||
thWidth = 180
|
||||
}
|
||||
|
||||
$('.lastTh').css("width", `${thWidth}px`);
|
||||
$('#{{view_id}} .lastTh').css("width", `${thWidth}px`);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{% load generic_template_filters %}
|
||||
<div id="{{view_id}}">
|
||||
{% for field_tuple in dynamic_create_fields %}
|
||||
<div
|
||||
@@ -12,18 +13,28 @@
|
||||
id="dynamicModal{{field_tuple.0}}Body"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<form id="{{view_id}}Form" hx-post="{{request.path}}?{{request.GET.urlencode}}" hx-encoding="multipart/form-data" hx-swap="outerHTML" {% if hx_confirm %} hx-confirm="{{hx_confirm}}" {% endif %}>{{form.structured}}</form>
|
||||
{% for field_tuple in dynamic_create_fields %}
|
||||
<div >
|
||||
<script class="dynamic_{{field_tuple.0}}_scripts">
|
||||
{{form.initial|get_item:field_tuple.0}}
|
||||
$("#{{view_id}}Form [name={{field_tuple.0}}]").val({{form.initial|get_item:field_tuple.0|safe}}).change()
|
||||
</script>
|
||||
|
||||
<form
|
||||
hidden
|
||||
id="modalButton{{field_tuple.0}}Form"
|
||||
hx-get="/dynamic-path-{{field_tuple.0}}-{{request.session.session_key}}?dynamic_field={{field_tuple.0}}"
|
||||
hx-target="#dynamicModal{{field_tuple.0}}Body"
|
||||
>
|
||||
<input type="hidden" name="dynamic_initial" data-dynamic-field="{{field_tuple.0}}">
|
||||
<input type="hidden" name="view_id" value="{{view_id}}">
|
||||
<input type="text" name="dynamic_initial" data-dynamic-field="{{field_tuple.0}}">
|
||||
<input type="text" name="view_id" value="{{view_id}}">
|
||||
{% for field in field_tuple.2 %}
|
||||
<input type="text" name="{{field}}">
|
||||
{% endfor %}
|
||||
<button
|
||||
hidden
|
||||
type="submit"
|
||||
id="modalButton{{field_tuple.0}}"
|
||||
onclick="$('#dynamicModal{{field_tuple.0}}').addClass('oh-modal--show');"
|
||||
@@ -31,16 +42,19 @@
|
||||
{{field_tuple.0}}
|
||||
</button>
|
||||
</form>
|
||||
<form id="reload-field{{field_tuple.0}}{{view_id}}" hx-get="{% url "reload-field" %}?form_class_path={{form_class_path}}&dynamic_field={{field_tuple.0}}" hx-target="#dynamic_field_{{field_tuple.0}}">
|
||||
<input type="hidden" name="dynamic_initial" data-dynamic-field="{{field_tuple.0}}">
|
||||
<input type="hidden" name="view_id" value="{{view_id}}">
|
||||
<button hidden class="reload-field" data-target="{{field_tuple.0}}">
|
||||
Reload Field
|
||||
<form hidden id="reload-field{{field_tuple.0}}{{view_id}}" hx-get="{% url "reload-field" %}?form_class_path={{form_class_path}}&dynamic_field={{field_tuple.0}}" hx-target="#dynamic_field_{{field_tuple.0}}">
|
||||
<input type="text" name="dynamic_initial" data-dynamic-field="{{field_tuple.0}}">
|
||||
<input type="text" name="view_id" value="{{view_id}}">
|
||||
<button class="reload-field" data-target="{{field_tuple.0}}">
|
||||
{{field_tuple.0}}
|
||||
</button>
|
||||
</form>
|
||||
<script>
|
||||
<script class="dynamic_{{field_tuple.0}}_scripts">
|
||||
$("#{{view_id}}Form [name={{field_tuple.0}}]").change(function (e) {
|
||||
values = $(this).val();
|
||||
if (!values) {
|
||||
values = ""
|
||||
}
|
||||
if (values == "dynamic_create") {
|
||||
$("#modalButton{{field_tuple.0}}").click()
|
||||
$(this).val("")
|
||||
@@ -51,6 +65,9 @@
|
||||
$("#modalButton{{field_tuple.0}}").parent().find('input[name=dynamic_initial]').val(values)
|
||||
$("#reload-field{{field_tuple.0}}{{view_id}}").find('input[name=dynamic_initial]').val(values)
|
||||
$("#modalButton{{field_tuple.0}}").click()
|
||||
}else if(values) {
|
||||
$("#modalButton{{field_tuple.0}}").parent().find('input[name=dynamic_initial]').val(values)
|
||||
$("#reload-field{{field_tuple.0}}{{view_id}}").find('input[name=dynamic_initial]').val(values)
|
||||
}
|
||||
});
|
||||
$("#reload-field{{field_tuple.0}}{{view_id}}").submit(function (e) {
|
||||
@@ -58,5 +75,6 @@
|
||||
$(this).find("[name=dynamic_initial]").val();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -335,6 +335,9 @@
|
||||
if (widths.length) {
|
||||
thWidth = widths[0];
|
||||
}
|
||||
if (!thWidth) {
|
||||
thWidth = 180
|
||||
}
|
||||
$('#{{view_id}} .lastTh').css("width", `${thWidth}px`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
hx-on:submit="htmxLoadIndicator(this);"
|
||||
class="oh-main__titlebar oh-main__titlebar--right"
|
||||
>
|
||||
<input type="text" name="nav_url" value="{{request.path}}" hidden>
|
||||
<div class="oh-input-group oh-input__search-group" id="searchGroup">
|
||||
<ion-icon
|
||||
name="search-outline"
|
||||
@@ -236,6 +237,9 @@
|
||||
var data ={{last_filter|safe}}
|
||||
for (const key in data) {
|
||||
const field = form.elements[key];
|
||||
if ({{empty_inputs|safe}}.includes(key)) {
|
||||
continue
|
||||
}
|
||||
const value = data[key][0]; // Get the first element in the array
|
||||
|
||||
if (field) {
|
||||
|
||||
@@ -110,6 +110,10 @@
|
||||
$("div.oh-tabs").find(`{{active_target|safe}}`).click();
|
||||
if (!$(".oh-tabs__tab--active").length) {
|
||||
$("#{{view_id}}").find(".oh-tabs__tab").first().click()
|
||||
}else{
|
||||
setTimeout(() => {
|
||||
$(".oh-tabs__tab--active").click();
|
||||
}, 100);
|
||||
}
|
||||
{% endif %}
|
||||
</script>
|
||||
|
||||
@@ -1,23 +1,31 @@
|
||||
<div id="{{dynamic_id}}">
|
||||
{{field}}
|
||||
</dic>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
dynamic_value = $("#{{dynamic_id}} [name={{field.name}}]").val()
|
||||
dynamic_value = {{field.initial|safe}}
|
||||
$("#reload-field{{field.name}}{{view_id}}").find('input[name=dynamic_initial]').val({{field.initial|safe}})
|
||||
$("#{{dynamic_id}} [name={{field.name}}]").val(dynamic_value).change()
|
||||
if (dynamic_value != "dynamic_create"){
|
||||
$("#{{dynamic_id}} [name={{field.name}}]").change()
|
||||
}
|
||||
$("#{{dynamic_id}} [name={{field.name}}]").change(function (e) {
|
||||
values = $(this).val();
|
||||
if (!values) {
|
||||
values = ""
|
||||
}
|
||||
if (values == "dynamic_create") {
|
||||
$("#modalButton{{field_tuple.0}}").click()
|
||||
$("#modalButton{{field.name}}").click()
|
||||
}else if (values.includes("dynamic_create")) {
|
||||
let index = values.indexOf("dynamic_create");
|
||||
values.splice(index, 1);
|
||||
$(this).val(values).change();
|
||||
$("#{{request.GET.view_id}} #modalButton{{field.name}}").parent().find('input[name=dynamic_initial]').val(values)
|
||||
$("#{{request.GET.view_id}} #reload-field{{field.name}}{{request.GET.view_id}}").find('input[name=dynamic_initial]').val(values)
|
||||
$("#{{request.GET.view_id}} #modalButton{{field.name}}").click()
|
||||
$("#modalButton{{field.name}}").parent().find('input[name=dynamic_initial]').val(values)
|
||||
$("#reload-field{{field.name}}{{request.GET.view_id}}").find('input[name=dynamic_initial]').val(values)
|
||||
$("#modalButton{{field.name}}").click()
|
||||
|
||||
}else {
|
||||
$("#modalButton{{field.name}}").parent().find('input[name=dynamic_initial]').val(values)
|
||||
$("#reload-field{{field.name}}{{view_id}}").find('input[name=dynamic_initial]').val(values)
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -71,7 +71,14 @@ class ReloadField(View):
|
||||
parent_form = getattr(module, class_name)()
|
||||
|
||||
dynamic_cache = CACHE.get(request.session.session_key + "cbv" + reload_field)
|
||||
onchange = CACHE.get(
|
||||
request.session.session_key + "cbv" + reload_field + "onchange"
|
||||
)
|
||||
if not onchange:
|
||||
onchange = ""
|
||||
|
||||
model: models.HorillaModel = dynamic_cache["model"]
|
||||
value = dynamic_cache.get("value", "")
|
||||
|
||||
cache_field = dynamic_cache["dynamic_field"]
|
||||
if cache_field != reload_field:
|
||||
@@ -87,6 +94,11 @@ class ReloadField(View):
|
||||
form_field = forms.ChoiceField
|
||||
if isinstance(field, forms.ModelMultipleChoiceField):
|
||||
form_field = forms.MultipleChoiceField
|
||||
dynamic_initial = request.GET.get("dynamic_initial", [])
|
||||
value = eval_validate(f"""[{dynamic_cache["value"]},{dynamic_initial}]""")
|
||||
else:
|
||||
if not value and self.request.GET.get("dynamic_initial"):
|
||||
value = eval_validate(self.request.GET.get("dynamic_initial"))
|
||||
|
||||
parent_form.fields[cache_field] = form_field(
|
||||
choices=choices,
|
||||
@@ -96,11 +108,9 @@ class ReloadField(View):
|
||||
parent_form.fields[cache_field].widget.option_template_name = (
|
||||
"horilla_widgets/select_option.html",
|
||||
)
|
||||
dynamic_initial = request.GET.get("dynamic_initial", [])
|
||||
parent_form.fields[cache_field].widget.attrs = field.widget.attrs
|
||||
parent_form.fields[cache_field].initial = eval_validate(
|
||||
f"""[{dynamic_cache["value"]},{dynamic_initial}]"""
|
||||
)
|
||||
parent_form.fields[cache_field].initial = value
|
||||
parent_form.fields[cache_field].widget.attrs["onchange"] = onchange
|
||||
|
||||
field = parent_form[cache_field]
|
||||
dynamic_id: str = get_short_uuid(4)
|
||||
@@ -257,11 +267,16 @@ class LastAppliedFilter(View):
|
||||
"""
|
||||
Get method
|
||||
"""
|
||||
CACHE.set(
|
||||
self.request.session.session_key + "last-applied-filter",
|
||||
self.request.GET,
|
||||
timeout=600,
|
||||
|
||||
nav_path = self.request.GET.get(
|
||||
"nav_url",
|
||||
)
|
||||
if nav_path:
|
||||
CACHE.set(
|
||||
self.request.session.session_key + "last-applied-filter" + nav_path,
|
||||
self.request.GET,
|
||||
timeout=600,
|
||||
)
|
||||
return HttpResponse("success")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user