[UPDT] HORILLA VIEWS: Bulk select widget design
This commit is contained in:
@@ -130,6 +130,16 @@ class DynamicBulkUpdateForm(forms.Form):
|
||||
)
|
||||
continue
|
||||
elif not getattribute(val, "related_model"):
|
||||
if isinstance(val, models.models.CharField) and val.choices:
|
||||
self.fields[key] = forms.ChoiceField(
|
||||
choices=val.choices,
|
||||
widget=forms.Select(
|
||||
attrs={"class": "oh-select oh-select-2 w-100"}
|
||||
),
|
||||
label=val.verbose_name.capitalize(),
|
||||
required=False,
|
||||
)
|
||||
continue
|
||||
self.fields[key] = field(
|
||||
widget=widget,
|
||||
label=val.verbose_name.capitalize(),
|
||||
|
||||
@@ -827,11 +827,16 @@ class HorillaFormView(FormView):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
self.form_class_path = (
|
||||
self.get_form().__class__.__module__ + "." + self.form.__class__.__name__
|
||||
)
|
||||
|
||||
context["dynamic_create_fields"] = self.dynamic_create_fields
|
||||
context["form_class_path"] = self.form_class_path
|
||||
context["view_id"] = self.view_id
|
||||
pk = self.form.instance.pk
|
||||
pk = None
|
||||
if self.form.instance:
|
||||
pk = self.form.instance.pk
|
||||
# next/previous option in the forms
|
||||
if pk and self.request.GET.get(self.ids_key):
|
||||
instance_ids = eval(str(self.request.GET.get(self.ids_key)))
|
||||
@@ -852,75 +857,75 @@ class HorillaFormView(FormView):
|
||||
return context
|
||||
|
||||
def get_form(self, form_class=None):
|
||||
pk = self.kwargs.get("pk")
|
||||
instance = self.model.objects.filter(pk=pk).first()
|
||||
data = None
|
||||
files = None
|
||||
if self.request.method == "POST":
|
||||
data = self.request.POST
|
||||
files = self.request.FILES
|
||||
form = self.form_class(data, files, instance=instance)
|
||||
if not hasattr(self, "form"):
|
||||
pk = self.kwargs.get("pk")
|
||||
instance = self.model.objects.filter(pk=pk).first()
|
||||
data = None
|
||||
files = None
|
||||
if self.request.method == "POST":
|
||||
data = self.request.POST
|
||||
files = self.request.FILES
|
||||
form = self.form_class(data, files, instance=instance)
|
||||
|
||||
if self.is_dynamic_create_view:
|
||||
setattr(type(form), "save", save)
|
||||
if self.is_dynamic_create_view:
|
||||
setattr(type(form), "save", save)
|
||||
|
||||
self.form_class_path = form.__class__.__module__ + "." + form.__class__.__name__
|
||||
if self.request.method == "GET":
|
||||
[
|
||||
(
|
||||
"employee_id",
|
||||
FormView,
|
||||
)
|
||||
]
|
||||
for dynamic_tuple in self.dynamic_create_fields:
|
||||
view = dynamic_tuple[1]
|
||||
view.display_title = "Dynamic create"
|
||||
field = dynamic_tuple[0]
|
||||
key = self.request.session.session_key + "cbv" + field
|
||||
CACHE.set(
|
||||
key,
|
||||
{
|
||||
"dynamic_field": field,
|
||||
"value": getattribute(form.instance, field),
|
||||
"model": form._meta.model,
|
||||
},
|
||||
)
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from horilla.urls import urlpatterns
|
||||
|
||||
urlpatterns.append(
|
||||
path(
|
||||
f"dynamic-path-{field}-{self.request.session.session_key}",
|
||||
view.as_view(),
|
||||
name=f"dynamic-path-{field}-{self.request.session.session_key}",
|
||||
if self.request.method == "GET":
|
||||
[
|
||||
(
|
||||
"employee_id",
|
||||
FormView,
|
||||
)
|
||||
)
|
||||
queryset = form.fields[field].queryset
|
||||
choices = [(instance.id, instance) for instance in queryset]
|
||||
choices.insert(0, ("", "Select option"))
|
||||
choices.append(("dynamic_create", "Dynamic create"))
|
||||
form.fields[field] = forms.ChoiceField(
|
||||
choices=choices,
|
||||
label=form.fields[field].label,
|
||||
required=form.fields[field].required,
|
||||
widget=forms.Select(attrs=form.fields[field].widget.attrs),
|
||||
)
|
||||
if pk:
|
||||
form.instance = instance
|
||||
title = str(instance)
|
||||
if self.form_disaply_attr:
|
||||
title = getattribute(instance, self.form_disaply_attr)
|
||||
if instance:
|
||||
self.form_class.verbose_name = title
|
||||
else:
|
||||
self.form_class.verbose_name = self.new_display_title
|
||||
form.close_button_attrs = self.close_button_attrs
|
||||
form.submit_button_attrs = self.submit_button_attrs
|
||||
CACHE.get(self.request.session.session_key + "cbv")[HorillaFormView] = form
|
||||
self.form = form
|
||||
return form
|
||||
]
|
||||
for dynamic_tuple in self.dynamic_create_fields:
|
||||
view = dynamic_tuple[1]
|
||||
view.display_title = "Dynamic create"
|
||||
field = dynamic_tuple[0]
|
||||
key = self.request.session.session_key + "cbv" + field
|
||||
CACHE.set(
|
||||
key,
|
||||
{
|
||||
"dynamic_field": field,
|
||||
"value": getattribute(form.instance, field),
|
||||
"model": form._meta.model,
|
||||
},
|
||||
)
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from horilla.urls import urlpatterns
|
||||
|
||||
urlpatterns.append(
|
||||
path(
|
||||
f"dynamic-path-{field}-{self.request.session.session_key}",
|
||||
view.as_view(),
|
||||
name=f"dynamic-path-{field}-{self.request.session.session_key}",
|
||||
)
|
||||
)
|
||||
queryset = form.fields[field].queryset
|
||||
choices = [(instance.id, instance) for instance in queryset]
|
||||
choices.insert(0, ("", "Select option"))
|
||||
choices.append(("dynamic_create", "Dynamic create"))
|
||||
form.fields[field] = forms.ChoiceField(
|
||||
choices=choices,
|
||||
label=form.fields[field].label,
|
||||
required=form.fields[field].required,
|
||||
widget=forms.Select(attrs=form.fields[field].widget.attrs),
|
||||
)
|
||||
if pk:
|
||||
form.instance = instance
|
||||
title = str(instance)
|
||||
if self.form_disaply_attr:
|
||||
title = getattribute(instance, self.form_disaply_attr)
|
||||
if instance:
|
||||
self.form_class.verbose_name = title
|
||||
else:
|
||||
self.form_class.verbose_name = self.new_display_title
|
||||
form.close_button_attrs = self.close_button_attrs
|
||||
form.submit_button_attrs = self.submit_button_attrs
|
||||
CACHE.get(self.request.session.session_key + "cbv")[HorillaFormView] = form
|
||||
self.form = form
|
||||
return self.form
|
||||
|
||||
|
||||
@method_decorator(hx_request_required, name="dispatch")
|
||||
|
||||
@@ -16,102 +16,7 @@
|
||||
}
|
||||
</script>
|
||||
{% if bulk_select_option %}
|
||||
<div class="d-flex justify-content-between">
|
||||
<div>
|
||||
<div class="oh-checkpoint-badge text-success"
|
||||
onclick="
|
||||
addToSelectedId({{select_all_ids|safe}},'{{selected_instances_key_id}}');
|
||||
selectSelected('#{{view_id|safe}}','{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
"
|
||||
style="cursor: pointer;">
|
||||
{% trans "Select All" %} ({{queryset.paginator.count}})
|
||||
</div>
|
||||
<div
|
||||
id="unselect_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-secondary d-none"
|
||||
style="cursor: pointer;"
|
||||
onclick="
|
||||
$('#{{selected_instances_key_id}}').attr('data-ids',JSON.stringify([]));
|
||||
selectSelected('#{{view_id|safe}}','{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
$('#{{view_id}} .list-table-row').prop('checked',false);
|
||||
$('#{{view_id}} .highlight-selected').removeClass('highlight-selected');
|
||||
$('#{{view_id}} .bulk-list-table-row').prop('checked',false);
|
||||
"
|
||||
>
|
||||
{% trans "Unselect All" %}
|
||||
</div>
|
||||
<div class="oh-checkpoint-badge text-danger d-none"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<span id="count_{{view_id}}">
|
||||
0
|
||||
</span> {% trans "Selected" %}
|
||||
</div>
|
||||
<div
|
||||
id="export_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-info d-none"
|
||||
style="cursor: pointer;"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#exportFields{{view_id|safe}}"
|
||||
>
|
||||
{% trans "Export" %}
|
||||
</div>
|
||||
{% if bulk_path %}
|
||||
<div
|
||||
id="bulk_udate_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-warning d-none"
|
||||
style="cursor: pointer;"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#bulkUpdateModal{{view_id|safe}}"
|
||||
onclick="
|
||||
ids = $('#{{selected_instances_key_id}}').attr('data-ids')
|
||||
$('#bulk_update_get_form{{view_id}}').closest('form').find('[name=instance_ids]').val(ids);
|
||||
$('#bulk_update_get_form{{view_id}}').click()
|
||||
"
|
||||
>
|
||||
{% trans "Update" %}
|
||||
</div>
|
||||
<form
|
||||
hx-get="/{{bulk_path}}"
|
||||
hx-target="#bulkUpdateModalBody{{view_id|safe}}">
|
||||
<input type="hidden" name="instance_ids">
|
||||
<button type="submit" id="bulk_update_get_form{{view_id}}" hidden>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% for filter in stored_filters %}
|
||||
<div class="oh-hover-btn-container"
|
||||
hx-get="{{request.path}}?{{filter.urlencode}}"
|
||||
hx-target="#{{view_id|safe}}" hx-swap="outerHTML"
|
||||
>
|
||||
<button class="oh-hover-btn" style="
|
||||
cursor: pointer;
|
||||
border: solid 2px {{filter.color}};
|
||||
color: {{filter.color}} !important;
|
||||
">
|
||||
{{filter.title}}
|
||||
</button>
|
||||
<div class="oh-hover-btn-drawer" onclick="event.stopPropagation()">
|
||||
<button class="oh-hover-btn__small" onclick="$('#savedFilterModal').addClass('oh-modal--show')" hx-get="{% url "saved-filter-update" filter.id %}" hx-target="#SavedFilterFormTarget" hx-swap="innerHTML"><ion-icon name="create-outline"></ion-icon></button>
|
||||
<button class="oh-hover-btn__small" onclick="$(this).parent().find('button:hidden').click();$(this).closest('.oh-hover-btn-container').remove()" ><ion-icon name="trash-outline"></ion-icon></button>
|
||||
<button hidden hx-get="{% url "delete-saved-filter" filter.id %}" hx-swap="none"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% if row_status_indications %}
|
||||
<div class="d-flex flex-row-reverse">
|
||||
{% for indication in row_status_indications %}
|
||||
<span class="m-1" style="cursor: pointer;margin-left: 7px;" {{indication.2|safe}}>
|
||||
<span class="oh-dot oh-dot--small me-1 {{indication.0}}"></span>
|
||||
{{indication.1}}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "generic/quick_actions.html" %}
|
||||
{% endif %}
|
||||
<button class="reload-record" hidden hx-get="{{request.path}}?{{request.GET.urlencode}}" hx-target="#{{view_id|safe}}" hx-swap="outerHTML">
|
||||
</button>
|
||||
@@ -146,7 +51,7 @@
|
||||
<div class="oh-tabs__input-badge-container">
|
||||
<span
|
||||
class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round mr-1"
|
||||
title="5 Candidates"
|
||||
title="{{group.list.paginator.count}} {% trans "Records" %}"
|
||||
>
|
||||
{{group.list.paginator.count}}
|
||||
</span>
|
||||
@@ -178,6 +83,7 @@
|
||||
$(this).closest('.oh-sticky-table').find('.list-table-row').prop('checked',$(this).is(':checked')).change();
|
||||
$(document).ready(function () {
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
});
|
||||
"
|
||||
title="Select All"
|
||||
@@ -229,6 +135,7 @@
|
||||
removeId(element)
|
||||
}
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
});
|
||||
"
|
||||
value = "{{instance.pk}}"
|
||||
@@ -416,6 +323,8 @@
|
||||
</nav>
|
||||
</div>
|
||||
<script>
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
var tabId = $("#{{view_id}}").closest(".oh-tabs__content").attr("id")
|
||||
let badge = $(`#badge-${tabId}`)
|
||||
let count = "{{queryset.paginator.count}}"
|
||||
|
||||
@@ -21,103 +21,7 @@
|
||||
{% if show_filter_tags %} {% include "generic/filter_tags.html" %} {% endif %}
|
||||
{% if queryset|length %}
|
||||
{% if bulk_select_option %}
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<div>
|
||||
<div class="oh-checkpoint-badge text-success"
|
||||
onclick="
|
||||
addToSelectedId({{select_all_ids|safe}},'{{selected_instances_key_id}}');
|
||||
selectSelected('#{{view_id|safe}}','{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
"
|
||||
style="cursor: pointer;">
|
||||
{% trans "Select All" %} ({{queryset.paginator.count}})
|
||||
</div>
|
||||
<div
|
||||
id="unselect_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-secondary d-none"
|
||||
style="cursor: pointer;"
|
||||
onclick="
|
||||
$('#{{selected_instances_key_id}}').attr('data-ids',JSON.stringify([]));
|
||||
selectSelected('#{{view_id|safe}}','{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
$('#{{view_id}} .list-table-row').prop('checked',false);
|
||||
$('#{{view_id}} .highlight-selected').removeClass('highlight-selected');
|
||||
$('#{{view_id}} .bulk-list-table-row').prop('checked',false);
|
||||
"
|
||||
>
|
||||
{% trans "Unselect All" %}
|
||||
</div>
|
||||
<div class="oh-checkpoint-badge text-danger d-none"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<span id="count_{{view_id}}">
|
||||
0
|
||||
</span> {% trans "Selected" %}
|
||||
</div>
|
||||
<div
|
||||
id="export_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-info d-none"
|
||||
style="cursor: pointer;"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#exportFields{{view_id|safe}}"
|
||||
>
|
||||
{% trans "Export" %}
|
||||
</div>
|
||||
{% if bulk_path %}
|
||||
<div
|
||||
id="bulk_udate_{{view_id}}"
|
||||
class="oh-checkpoint-badge text-warning d-none"
|
||||
style="cursor: pointer;"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#bulkUpdateModal{{view_id|safe}}"
|
||||
onclick="
|
||||
ids = $('#{{selected_instances_key_id}}').attr('data-ids')
|
||||
$('#bulk_update_get_form{{view_id}}').closest('form').find('[name=instance_ids]').val(ids);
|
||||
$('#bulk_update_get_form{{view_id}}').click()
|
||||
"
|
||||
>
|
||||
{% trans "Update" %}
|
||||
</div>
|
||||
<form
|
||||
hx-get="/{{bulk_path}}"
|
||||
hx-target="#bulkUpdateModalBody{{view_id|safe}}">
|
||||
<input type="hidden" name="instance_ids">
|
||||
<button type="submit" id="bulk_update_get_form{{view_id}}" hidden>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% for filter in stored_filters %}
|
||||
<div class="oh-hover-btn-container"
|
||||
hx-get="{{request.path}}?{{filter.urlencode}}"
|
||||
hx-target="#{{view_id|safe}}" hx-swap="outerHTML"
|
||||
>
|
||||
<button class="oh-hover-btn" style="
|
||||
cursor: pointer;
|
||||
border: solid 2px {{filter.color}};
|
||||
color: {{filter.color}} !important;
|
||||
">
|
||||
{{filter.title}}
|
||||
</button>
|
||||
<div class="oh-hover-btn-drawer" onclick="event.stopPropagation()">
|
||||
<button class="oh-hover-btn__small" onclick="$('#savedFilterModal').addClass('oh-modal--show')" hx-get="{% url "saved-filter-update" filter.id %}" hx-target="#SavedFilterFormTarget" hx-swap="innerHTML"><ion-icon name="create-outline"></ion-icon></button>
|
||||
<button class="oh-hover-btn__small" onclick="$(this).parent().find('button:hidden').click();$(this).closest('.oh-hover-btn-container').remove()" ><ion-icon name="trash-outline"></ion-icon></button>
|
||||
<button hidden hx-get="{% url "delete-saved-filter" filter.id %}" hx-swap="none"></button>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% if row_status_indications %}
|
||||
<div class="d-flex flex-row-reverse">
|
||||
{% for indication in row_status_indications %}
|
||||
<span class="m-1" style="cursor: pointer;margin-left: 7px;" {{indication.2|safe}}>
|
||||
<span class="oh-dot oh-dot--small me-1 {{indication.0}}"></span>
|
||||
{{indication.1}}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "generic/quick_actions.html" %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -166,6 +70,7 @@
|
||||
$(this).closest('.oh-sticky-table').find('.list-table-row').prop('checked',$(this).is(':checked')).change();
|
||||
$(document).ready(function () {
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
});
|
||||
"
|
||||
title="Select All"
|
||||
@@ -241,6 +146,7 @@
|
||||
removeId(element)
|
||||
}
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
});
|
||||
"
|
||||
value = "{{instance.pk}}"
|
||||
@@ -387,6 +293,7 @@
|
||||
</div>
|
||||
<script>
|
||||
reloadSelectedCount($('#count_{{view_id|safe}}'),'{{selected_instances_key_id}}');
|
||||
reloadSelectedCount($('.count_{{view_id|safe}}'));
|
||||
var tabId = $("#{{view_id}}").closest(".oh-tabs__content").attr("id");
|
||||
let badge = $(`#badge-${tabId}`);
|
||||
let count = "{{queryset.paginator.count}}";
|
||||
|
||||
Reference in New Issue
Block a user