update the perms
This commit is contained in:
parent
90425409fd
commit
68f7e3fb2c
@ -1596,8 +1596,8 @@ class PermissionForm(forms.ModelForm):
|
|||||||
# "inventory.salequotation",
|
# "inventory.salequotation",
|
||||||
# "inventory.salequotationcar"
|
# "inventory.salequotationcar"
|
||||||
|
|
||||||
|
"django_ledger.purchaseordermodel"
|
||||||
"django_ledger.bankaccountmodel",
|
"django_ledger.bankaccountmodel",
|
||||||
"django_ledger.chartofaccountmodel",
|
|
||||||
"django_ledger.estimatemodel",
|
"django_ledger.estimatemodel",
|
||||||
"django_ledger.accountmodel",
|
"django_ledger.accountmodel",
|
||||||
"django_ledger.chartofaccountmodel",
|
"django_ledger.chartofaccountmodel",
|
||||||
@ -1606,7 +1606,7 @@ class PermissionForm(forms.ModelForm):
|
|||||||
"django_ledger.invoicemodel",
|
"django_ledger.invoicemodel",
|
||||||
"django_ledger.vendormodel",
|
"django_ledger.vendormodel",
|
||||||
"django_ledger.journalentrymodel"
|
"django_ledger.journalentrymodel"
|
||||||
# "django_ledger.purchaseordermodel",#TODO add purchase order
|
"django_ledger.purchaseordermodel",#TODO add purchase order
|
||||||
]
|
]
|
||||||
|
|
||||||
permissions = cache.get(
|
permissions = cache.get(
|
||||||
|
|||||||
@ -2661,8 +2661,9 @@ class CustomGroup(models.Model):
|
|||||||
"invoicemodel",
|
"invoicemodel",
|
||||||
"vendormodel",
|
"vendormodel",
|
||||||
"journalentrymodel",
|
"journalentrymodel",
|
||||||
|
"purchaseordermodel",
|
||||||
],
|
],
|
||||||
other_perms=["view_customermodel", "view_estimatemodel"],
|
other_perms=["view_customermodel", "view_estimatemodel","can_approve_estimatemodel","can_approve_billmodel"],
|
||||||
)
|
)
|
||||||
elif self.name == "Agent":
|
elif self.name == "Agent":
|
||||||
# Todo : set permissions for agent
|
# Todo : set permissions for agent
|
||||||
|
|||||||
@ -650,8 +650,15 @@ def inventory_table(context, queryset):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def count_checked(permissions):
|
def count_checked(permissions, group_permission_ids):
|
||||||
"""Count how many permissions are marked as checked"""
|
"""Count how many permissions are checked from the allowed list"""
|
||||||
print(permissions)
|
if not group_permission_ids:
|
||||||
return sum(1 for perm in permissions if getattr(perm, 'is_checked', False))
|
return 0
|
||||||
|
return sum(1 for perm in permissions if perm.id in group_permission_ids)
|
||||||
|
|
||||||
|
# @register.filter
|
||||||
|
# def count_checked(permissions, group_permission_ids):
|
||||||
|
# """Count how many permissions are checked from the allowed list"""
|
||||||
|
# return sum(1 for perm in permissions if perm.id in group_permission_ids)
|
||||||
@ -2756,78 +2756,269 @@ def GroupDeleteview(request, dealer_slug,pk):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
# def GroupPermissionView(request, dealer_slug, pk):
|
||||||
|
# # Verify dealer and group exist
|
||||||
|
# get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||||
|
# customgroup = get_object_or_404(models.CustomGroup, pk=pk)
|
||||||
|
|
||||||
|
# if request.method == "POST":
|
||||||
|
# form = forms.PermissionForm(request.POST, instance=customgroup)
|
||||||
|
# if form.is_valid():
|
||||||
|
# # Clear existing permissions
|
||||||
|
# customgroup.clear_permissions()
|
||||||
|
|
||||||
|
# # Add new permissions from form
|
||||||
|
# permissions = form.cleaned_data.get('permissions', [])
|
||||||
|
# for permission in permissions:
|
||||||
|
# customgroup.add_permission(permission)
|
||||||
|
|
||||||
|
# messages.success(request, _("Permissions updated successfully"))
|
||||||
|
# return redirect("group_detail", dealer_slug=dealer_slug, pk=customgroup.pk)
|
||||||
|
# else:
|
||||||
|
# # Initial form with current permissions
|
||||||
|
# form = forms.PermissionForm(instance=customgroup)
|
||||||
|
|
||||||
|
# group_permission_ids = set(customgroup.permissions.values_list('id', flat=True))
|
||||||
|
|
||||||
|
# # Mark permissions as checked in the form data
|
||||||
|
# for app_label, model in form.grouped_permissions.items():
|
||||||
|
# print(app_label, model)
|
||||||
|
# for mo, perms in model.items():
|
||||||
|
# for perm in perms:
|
||||||
|
# perm.is_checked = perm.id in group_permission_ids
|
||||||
|
|
||||||
|
# return render(request,"groups/group_permission_form.html", {
|
||||||
|
# "group": customgroup,
|
||||||
|
# "form": form,
|
||||||
|
# "group_permission_apps": set(customgroup.group.permissions.values_list('content_type__app_label', flat=True)),
|
||||||
|
# "group_permission_models": set(customgroup.group.permissions.values_list('content_type__model', flat=True))
|
||||||
|
# })
|
||||||
def GroupPermissionView(request, dealer_slug, pk):
|
def GroupPermissionView(request, dealer_slug, pk):
|
||||||
# Verify dealer and group exist
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.db import transaction
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
get_object_or_404(models.Dealer, slug=dealer_slug)
|
get_object_or_404(models.Dealer, slug=dealer_slug)
|
||||||
customgroup = get_object_or_404(models.CustomGroup, pk=pk)
|
customgroup = get_object_or_404(models.CustomGroup, pk=pk)
|
||||||
|
group = customgroup.group
|
||||||
|
# Define ALL permissions you want to manage
|
||||||
|
MODEL_LIST = [
|
||||||
|
("inventory", "car"),
|
||||||
|
("inventory", "carfinance"),
|
||||||
|
("inventory", "carlocation"),
|
||||||
|
("inventory", "customcard"),
|
||||||
|
("inventory", "cartransfer"),
|
||||||
|
("inventory", "carcolors"),
|
||||||
|
("inventory", "carequipment"),
|
||||||
|
("inventory", "interiorcolors"),
|
||||||
|
("inventory", "exteriorcolors"),
|
||||||
|
("inventory", "lead"),
|
||||||
|
("inventory", "customgroup"),
|
||||||
|
("inventory", "saleorder"),
|
||||||
|
("inventory", "payment"),
|
||||||
|
("inventory", "staff"),
|
||||||
|
("inventory", "schedule"),
|
||||||
|
("inventory", "activity"),
|
||||||
|
("inventory", "opportunity"),
|
||||||
|
("inventory", "carreservation"),
|
||||||
|
("inventory", "customer"),
|
||||||
|
("inventory", "organization"),
|
||||||
|
|
||||||
|
("django_ledger", "purchaseordermodel"),
|
||||||
|
("django_ledger", "bankaccountmodel"),
|
||||||
|
("django_ledger", "estimatemodel"),
|
||||||
|
("django_ledger", "accountmodel"),
|
||||||
|
("django_ledger", "chartofaccountmodel"),
|
||||||
|
("django_ledger", "billmodel"),
|
||||||
|
("django_ledger", "itemmodel"),
|
||||||
|
("django_ledger", "invoicemodel"),
|
||||||
|
("django_ledger", "vendormodel"),
|
||||||
|
("django_ledger", "journalentrymodel"),
|
||||||
|
("django_ledger", "purchaseordermodel"),
|
||||||
|
]
|
||||||
|
CUSTOM_PERMISSIONS = [
|
||||||
|
('django_ledger', 'can_approve_estimatemodel'),
|
||||||
|
('django_ledger', 'can_approve_billmodel'),
|
||||||
|
]
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = forms.PermissionForm(request.POST, instance=customgroup)
|
try:
|
||||||
if form.is_valid():
|
selected_ids = [int(id) for id in request.POST.getlist('permissions', [])]
|
||||||
# Clear existing permissions
|
|
||||||
customgroup.clear_permissions()
|
|
||||||
|
|
||||||
# Add new permissions from form
|
# Get content types for model permissions
|
||||||
permissions = form.cleaned_data.get('permissions', [])
|
model_content_types = ContentType.objects.filter(
|
||||||
for permission in permissions:
|
app_label__in=[m[0] for m in MODEL_LIST],
|
||||||
customgroup.add_permission(permission)
|
model__in=[m[1] for m in MODEL_LIST]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get all valid permissions (model CRUD + custom)
|
||||||
|
valid_perms = Permission.objects.filter(
|
||||||
|
# Model CRUD permissions
|
||||||
|
Q(content_type__in=model_content_types) |
|
||||||
|
# Custom permissions
|
||||||
|
Q(
|
||||||
|
content_type__app_label__in=[p[0] for p in CUSTOM_PERMISSIONS],
|
||||||
|
codename__in=[p[1] for p in CUSTOM_PERMISSIONS]
|
||||||
|
),
|
||||||
|
id__in=selected_ids
|
||||||
|
)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
group.permissions.clear()
|
||||||
|
if valid_perms.exists():
|
||||||
|
group.permissions.add(*valid_perms)
|
||||||
|
|
||||||
messages.success(request, _("Permissions updated successfully"))
|
messages.success(request, _("Permissions updated successfully"))
|
||||||
return redirect("group_detail", dealer_slug=dealer_slug, pk=customgroup.pk)
|
return redirect("group_detail", dealer_slug=dealer_slug, pk=customgroup.pk)
|
||||||
else:
|
|
||||||
# Initial form with current permissions
|
|
||||||
form = forms.PermissionForm(instance=customgroup)
|
|
||||||
|
|
||||||
group_permission_ids = set(customgroup.permissions.values_list('id', flat=True))
|
except Exception as e:
|
||||||
|
messages.error(request, _("Error updating permissions: ") + str(e))
|
||||||
|
|
||||||
# Mark permissions as checked in the form data
|
# GET request handling
|
||||||
for app_label, model in form.grouped_permissions.items():
|
# Get permissions for models (CRUD)
|
||||||
for mo, perms in model.items():
|
model_perms = Permission.objects.filter(
|
||||||
for perm in perms:
|
content_type__in=ContentType.objects.filter(
|
||||||
perm.is_checked = perm.id in group_permission_ids
|
app_label__in=[m[0] for m in MODEL_LIST],
|
||||||
|
model__in=[m[1] for m in MODEL_LIST]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return render(request,"groups/group_permission_form.html", {
|
# Get custom permissions
|
||||||
|
custom_perms = Permission.objects.filter(
|
||||||
|
content_type__app_label__in=[p[0] for p in CUSTOM_PERMISSIONS],
|
||||||
|
codename__in=[p[1] for p in CUSTOM_PERMISSIONS]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Combine all permissions
|
||||||
|
all_permissions = model_perms | custom_perms
|
||||||
|
all_permissions = all_permissions.select_related('content_type').order_by(
|
||||||
|
'content_type__app_label', 'content_type__model', 'codename'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Group permissions with custom ones in a special section
|
||||||
|
grouped_permissions = {}
|
||||||
|
for perm in all_permissions:
|
||||||
|
app_label = perm.content_type.app_label
|
||||||
|
|
||||||
|
# Check if this is a custom permission
|
||||||
|
is_custom = any(
|
||||||
|
p[0] == app_label and p[1] == perm.codename
|
||||||
|
for p in CUSTOM_PERMISSIONS
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_custom:
|
||||||
|
# Group custom permissions under "Custom" model name
|
||||||
|
model = "Custom"
|
||||||
|
else:
|
||||||
|
model = perm.content_type.model
|
||||||
|
|
||||||
|
if app_label not in grouped_permissions:
|
||||||
|
grouped_permissions[app_label] = {}
|
||||||
|
if model not in grouped_permissions[app_label]:
|
||||||
|
grouped_permissions[app_label][model] = []
|
||||||
|
|
||||||
|
grouped_permissions[app_label][model].append(perm)
|
||||||
|
|
||||||
|
# Get currently assigned permission IDs
|
||||||
|
group_permission_ids = set(
|
||||||
|
group.permissions.filter(
|
||||||
|
id__in=all_permissions.values_list('id', flat=True)
|
||||||
|
).values_list('id', flat=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
return render(request, "groups/group_permission_form.html", {
|
||||||
"group": customgroup,
|
"group": customgroup,
|
||||||
"form": form,
|
"grouped_permissions": grouped_permissions,
|
||||||
"group_permission_apps": set(customgroup.group.permissions.values_list('content_type__app_label', flat=True)),
|
"group_permission_ids": group_permission_ids,
|
||||||
"group_permission_models": set(customgroup.group.permissions.values_list('content_type__model', flat=True))
|
"group_permission_apps": set(
|
||||||
|
group.permissions.filter(
|
||||||
|
content_type__app_label__in=grouped_permissions.keys()
|
||||||
|
).values_list('content_type__app_label', flat=True)
|
||||||
|
),
|
||||||
|
"group_permission_models": set(
|
||||||
|
group.permissions.filter(
|
||||||
|
content_type__app_label__in=grouped_permissions.keys()
|
||||||
|
).values_list('content_type__model', flat=True)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
# def GroupPermissionView(request, dealer_slug,pk):
|
# if request.method == "POST":
|
||||||
# """
|
# try:
|
||||||
# Handles the view for adding or modifying permissions of a specific group. This view
|
# selected_ids = [int(id) for id in request.POST.getlist('permissions', [])]
|
||||||
# fetches the group based on the primary key passed as a parameter, and either displays
|
|
||||||
# a form for editing permissions or processes the submitted permissions.
|
|
||||||
|
|
||||||
# If the request method is POST, the permissions of the group are cleared and updated
|
# # Get all permission types for our models
|
||||||
# based on the submitted data. A success message is displayed upon completion, and
|
# content_types = ContentType.objects.filter(
|
||||||
# the user is redirected to the group's detail page.
|
# app_label__in=[m[0] for m in MODEL_LIST],
|
||||||
|
# model__in=[m[1] for m in MODEL_LIST]
|
||||||
|
# )
|
||||||
|
|
||||||
# In case of a GET request, the view renders the form pre-filled with the group's
|
# # Get valid permissions that exist for these models
|
||||||
# current permissions.
|
# valid_perms = Permission.objects.filter(
|
||||||
|
# content_type__in=content_types,
|
||||||
|
# id__in=selected_ids
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # Atomic transaction to ensure data consistency
|
||||||
|
# with transaction.atomic():
|
||||||
|
# # Clear current permissions
|
||||||
|
# group.permissions.clear()
|
||||||
|
|
||||||
|
# # Add new permissions if any were selected
|
||||||
|
# if valid_perms.exists():
|
||||||
|
# group.permissions.add(*valid_perms)
|
||||||
|
|
||||||
|
# messages.success(request, _("Permissions updated successfully"))
|
||||||
|
# return redirect("group_detail", dealer_slug=dealer_slug, pk=customgroup.pk)
|
||||||
|
|
||||||
|
# except Exception as e:
|
||||||
|
# messages.error(request, _("Error updating permissions: ") + str(e))
|
||||||
|
|
||||||
|
# # GET request handling
|
||||||
|
# content_types = ContentType.objects.filter(
|
||||||
|
# app_label__in=[m[0] for m in MODEL_LIST],
|
||||||
|
# model__in=[m[1] for m in MODEL_LIST]
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # Get all permissions for these content types
|
||||||
|
# all_permissions = Permission.objects.filter(
|
||||||
|
# content_type__in=content_types
|
||||||
|
# ).select_related('content_type').order_by('content_type__app_label', 'content_type__model', 'codename')
|
||||||
|
|
||||||
|
# # Group permissions by app and model
|
||||||
|
# grouped_permissions = {}
|
||||||
|
# for perm in all_permissions:
|
||||||
|
# app_label = perm.content_type.app_label
|
||||||
|
# model = perm.content_type.model
|
||||||
|
|
||||||
|
# if app_label not in grouped_permissions:
|
||||||
|
# grouped_permissions[app_label] = {}
|
||||||
|
# if model not in grouped_permissions[app_label]:
|
||||||
|
# grouped_permissions[app_label][model] = []
|
||||||
|
|
||||||
|
# grouped_permissions[app_label][model].append(perm)
|
||||||
|
|
||||||
|
# # Get currently assigned permission IDs
|
||||||
|
# group_permission_ids = set(
|
||||||
|
# group.permissions.filter(
|
||||||
|
# content_type__in=content_types
|
||||||
|
# ).values_list('id', flat=True)
|
||||||
|
# )
|
||||||
|
|
||||||
|
# return render(request, "groups/group_permission_form.html", {
|
||||||
|
# "group": customgroup,
|
||||||
|
# "grouped_permissions": grouped_permissions,
|
||||||
|
# "group_permission_ids": group_permission_ids,
|
||||||
|
# "group_permission_apps": set(
|
||||||
|
# group.permissions.filter(
|
||||||
|
# content_type__app_label__in=[m[0] for m in MODEL_LIST]
|
||||||
|
# ).values_list('content_type__app_label', flat=True)
|
||||||
|
# ),
|
||||||
|
# "group_permission_models": set(
|
||||||
|
# group.permissions.filter(
|
||||||
|
# content_type__model__in=[m[1] for m in MODEL_LIST]
|
||||||
|
# ).values_list('content_type__model', flat=True)
|
||||||
|
# )
|
||||||
|
# })
|
||||||
|
|
||||||
# :param request: The HTTP request object.
|
|
||||||
# :type request: HttpRequest
|
|
||||||
# :param pk: The primary key of the group whose permissions are being modified.
|
|
||||||
# :type pk: int
|
|
||||||
# :return: The HTTP response depending on the request type. For GET requests, renders
|
|
||||||
# the permission form for the specified group. For POST requests, clears and updates
|
|
||||||
# the group's permissions and redirects to the group's detail page.
|
|
||||||
# :rtype: HttpResponse
|
|
||||||
# """
|
|
||||||
# get_object_or_404(models.Dealer,slug=dealer_slug)
|
|
||||||
# group = get_object_or_404(models.CustomGroup, pk=pk)
|
|
||||||
# if request.method == "POST":
|
|
||||||
# form = forms.PermissionForm(request.POST)
|
|
||||||
# group.clear_permissions()
|
|
||||||
# permissions = request.POST.getlist("name")
|
|
||||||
# for i in permissions:
|
|
||||||
# group.add_permission(Permission.objects.get(id=int(i)))
|
|
||||||
# messages.success(request, _("Permission added successfully"))
|
|
||||||
# return redirect("group_detail", dealer_slug=dealer_slug,pk=group.pk)
|
|
||||||
# form = forms.PermissionForm(initial={"name": group.permissions})
|
|
||||||
# return render(
|
|
||||||
# request, "groups/group_permission_form.html", {"group": group, "form": form}
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
# Users
|
# Users
|
||||||
@ -9396,6 +9587,7 @@ def inventory_items_filter(request, dealer_slug):
|
|||||||
class PurchaseOrderDetailView(PurchaseOrderModelDetailViewBase):
|
class PurchaseOrderDetailView(PurchaseOrderModelDetailViewBase):
|
||||||
template_name = "purchase_orders/po_detail.html"
|
template_name = "purchase_orders/po_detail.html"
|
||||||
context_object_name = "po_model"
|
context_object_name = "po_model"
|
||||||
|
permission_required = ["inventory.view_carfinance"]
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
dealer = get_object_or_404(models.Dealer, slug=self.kwargs["dealer_slug"])
|
||||||
|
|||||||
@ -16,7 +16,9 @@
|
|||||||
{{ _("Add Permissions") }}
|
{{ _("Add Permissions") }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</h3>
|
</h3>
|
||||||
|
<div class="badge bg-primary rounded-pill">
|
||||||
|
{{ group_permission_ids|length }} {% trans "permissions assigned" %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -24,80 +26,108 @@
|
|||||||
<form method="post" novalidate>
|
<form method="post" novalidate>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|
||||||
|
<!-- Filter and Summary Section -->
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||||
|
<input type="text" class="form-control" id="permissionSearch"
|
||||||
|
placeholder="{% trans 'Search permissions...' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="alert alert-info py-2 mb-0">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>
|
||||||
|
{% trans "Checked items are currently assigned permissions" %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Permissions Grid -->
|
<!-- Permissions Grid -->
|
||||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4" id="permissionsGrid">
|
<!-- Permissions Grid -->
|
||||||
{% for app_label, models in form.grouped_permissions.items %}
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4" id="permissionsGrid">
|
||||||
<div class="col">
|
{% for app_label, models in grouped_permissions.items %}
|
||||||
<div class="card h-100 border-{% if app_label in group_permission_apps %}primary{% else %}light{% endif %}">
|
<div class="col">
|
||||||
<div class="card-header bg-{% if app_label in group_permission_apps %}primary text-white{% else %}light{% endif %}">
|
<div class="card h-100 border-{% if app_label in group_permission_apps %}primary{% else %}light{% endif %}">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="card-header bg-{% if app_label in group_permission_apps %}primary text-white{% else %}light{% endif %}">
|
||||||
<h5 class="card-title mb-0">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<i class="fas fa-{% if app_label in group_permission_apps %}check-circle{% else %}cube{% endif %} me-2"></i>
|
<h5 class="card-title mb-0">
|
||||||
{{ app_label|capfirst }}
|
<i class="fas fa-{% if app_label in group_permission_apps %}check-circle{% else %}cube{% endif %} me-2"></i>
|
||||||
</h5>
|
{{ app_label|capfirst }}
|
||||||
<span class="badge bg-{% if app_label in group_permission_apps %}light text-primary{% else %}secondary{% endif %}">
|
</h5>
|
||||||
{{ models|length }} {% trans "models" %}
|
<span class="badge bg-{% if app_label in group_permission_apps %}light text-primary{% else %}secondary{% endif %}">
|
||||||
|
{{ models|length }} {% trans "categories" %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="accordion" id="accordion-{{ app_label|slugify }}">
|
||||||
|
{% for model, perms in models.items %}
|
||||||
|
<div class="accordion-item border-0 mb-2">
|
||||||
|
<h6 class="accordion-header" id="heading-{{ app_label|slugify }}-{{ model|slugify }}">
|
||||||
|
<button class="accordion-button collapsed bg-white shadow-none py-2"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#collapse-{{ app_label|slugify }}-{{ model|slugify }}"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="collapse-{{ app_label|slugify }}-{{ model|slugify }}">
|
||||||
|
<i class="fas fa-{% if model == 'Custom' %}star{% else %}table{% endif %} me-2"></i>
|
||||||
|
{{ model|capfirst }}
|
||||||
|
<span class="badge bg-{% if model in group_permission_models %}primary{% else %}secondary{% endif %} rounded-pill ms-2">
|
||||||
|
{{ perms|length }} / {{ perms|count_checked:group_permission_ids }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</h6>
|
||||||
<div class="card-body">
|
<div id="collapse-{{ app_label|slugify }}-{{ model|slugify }}"
|
||||||
<div class="accordion">
|
class="accordion-collapse collapse"
|
||||||
{% for model, perms in models.items %}
|
aria-labelledby="heading-{{ app_label|slugify }}-{{ model|slugify }}"
|
||||||
<div class="accordion-item border-0">
|
data-bs-parent="#accordion-{{ app_label|slugify }}">
|
||||||
<h6 class="accordion-header" id="heading-{{ app_label|slugify }}-{{ model|slugify }}">
|
<div class="accordion-body pt-0 px-0">
|
||||||
<button class="accordion-button collapsed bg-white shadow-none py-2"
|
<div class="list-group list-group-flush">
|
||||||
type="button"
|
{% for perm in perms %}
|
||||||
data-bs-toggle="collapse"
|
<label class="list-group-item d-flex gap-2 {% if perm.id in group_permission_ids %}bg-light-primary{% endif %}">
|
||||||
data-bs-target="#collapse-{{ app_label|slugify }}-{{ model|slugify }}"
|
<input class="form-check-input flex-shrink-0 mt-0"
|
||||||
aria-expanded="false">
|
type="checkbox"
|
||||||
<i class="fas fa-table me-2"></i>{{ model|capfirst }}
|
name="permissions"
|
||||||
<span class="badge bg-{% if model in group_permission_models %}primary{% else %}secondary{% endif %} rounded-pill ms-2">
|
value="{{ perm.id }}"
|
||||||
{{ perms|length }} / {{ perms|count_checked }}
|
id="perm_{{ perm.id }}"
|
||||||
|
{% if perm.id in group_permission_ids %}checked{% endif %}>
|
||||||
|
<span>
|
||||||
|
<span class="d-block fw-bold">{{ perm.name|capfirst }}</span>
|
||||||
|
<small class="d-block text-muted">{{ perm.codename }}</small>
|
||||||
|
{% if model == 'Custom' %}
|
||||||
|
<span class="badge bg-info mt-1">
|
||||||
|
<i class="fas fa-star me-1"></i>{% trans "Custom" %}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
{% elif perm.id in group_permission_ids %}
|
||||||
</h6>
|
<span class="badge bg-success mt-1">
|
||||||
<div id="collapse-{{ app_label|slugify }}-{{ model|slugify }}"
|
<i class="fas fa-check me-1"></i>{% trans "Assigned" %}
|
||||||
class="accordion-collapse collapse"
|
</span>
|
||||||
aria-labelledby="heading-{{ app_label|slugify }}-{{ model|slugify }}">
|
{% endif %}
|
||||||
<div class="accordion-body pt-0">
|
</span>
|
||||||
<div class="list-group list-group-flush">
|
</label>
|
||||||
{% for perm in perms %}
|
{% endfor %}
|
||||||
<label class="list-group-item d-flex gap-2 {% if perm.is_checked %}bg-light-primary{% endif %}">
|
|
||||||
<input class="form-check-input flex-shrink-0 mt-0"
|
|
||||||
type="checkbox"
|
|
||||||
name="permissions"
|
|
||||||
value="{{ perm.id }}"
|
|
||||||
id="perm_{{ perm.id }}"
|
|
||||||
{% if perm.is_checked %}checked{% endif %}>
|
|
||||||
<span>
|
|
||||||
<span class="d-block fw-bold">{{ perm.name|capfirst }}</span>
|
|
||||||
<small class="d-block text-muted">{{ perm.codename }}</small>
|
|
||||||
{% if perm.is_checked %}
|
|
||||||
<span class="badge bg-success mt-1">
|
|
||||||
<i class="fas fa-check me-1"></i>{% trans "Assigned" %}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer section remains the same -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="d-flex justify-content-between align-items-center">
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
<div>
|
<div>
|
||||||
<span class="badge bg-primary rounded-pill me-2">
|
<span class="badge bg-primary rounded-pill me-2">
|
||||||
{{ group.permissions.count }} {% trans "selected" %}
|
{{ group_permission_ids|length }} {% trans "selected" %}
|
||||||
</span>
|
</span>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
{% trans "Permissions will be updated immediately" %}
|
{% trans "Permissions will be updated immediately" %}
|
||||||
@ -125,31 +155,59 @@
|
|||||||
.list-group-item:hover {
|
.list-group-item:hover {
|
||||||
background-color: rgba(0, 0, 0, 0.03);
|
background-color: rgba(0, 0, 0, 0.03);
|
||||||
}
|
}
|
||||||
|
.accordion-button:not(.collapsed) {
|
||||||
|
box-shadow: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.accordion-button:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
border-color: rgba(0,0,0,.125);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Search functionality
|
// Initialize all accordions
|
||||||
document.getElementById('permissionSearch').addEventListener('input', function(e) {
|
document.querySelectorAll('.accordion-button').forEach(button => {
|
||||||
const searchTerm = e.target.value.toLowerCase();
|
button.addEventListener('click', function() {
|
||||||
document.querySelectorAll('.accordion-body .list-group-item').forEach(item => {
|
const target = this.getAttribute('data-bs-target');
|
||||||
const text = item.textContent.toLowerCase();
|
new bootstrap.Collapse(target, {
|
||||||
item.style.display = text.includes(searchTerm) ? '' : 'none';
|
toggle: true
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open relevant accordions
|
|
||||||
document.querySelectorAll('.accordion-collapse').forEach(collapse => {
|
|
||||||
const visibleItems = collapse.querySelectorAll('.list-group-item[style=""]');
|
|
||||||
if (visibleItems.length > 0) {
|
|
||||||
const button = document.querySelector(
|
|
||||||
`button[data-bs-target="#${collapse.id}"]`
|
|
||||||
);
|
|
||||||
if (button && !button.classList.contains('collapsed')) {
|
|
||||||
new bootstrap.Collapse(collapse, {toggle: true});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Search functionality
|
||||||
|
const permissionSearch = document.getElementById('permissionSearch');
|
||||||
|
if (permissionSearch) {
|
||||||
|
permissionSearch.addEventListener('input', function(e) {
|
||||||
|
const searchTerm = e.target.value.toLowerCase();
|
||||||
|
let hasVisibleResults = false;
|
||||||
|
|
||||||
|
document.querySelectorAll('.accordion-body .list-group-item').forEach(item => {
|
||||||
|
const text = item.textContent.toLowerCase();
|
||||||
|
const isVisible = text.includes(searchTerm);
|
||||||
|
item.style.display = isVisible ? '' : 'none';
|
||||||
|
if (isVisible) hasVisibleResults = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open accordions with visible results
|
||||||
|
document.querySelectorAll('.accordion-collapse').forEach(collapse => {
|
||||||
|
const button = document.querySelector(`button[data-bs-target="#${collapse.id}"]`);
|
||||||
|
if (button) {
|
||||||
|
const hasVisible = collapse.querySelector('.list-group-item[style=""]');
|
||||||
|
const bsCollapse = bootstrap.Collapse.getInstance(collapse) ||
|
||||||
|
new bootstrap.Collapse(collapse);
|
||||||
|
|
||||||
|
if (hasVisible) {
|
||||||
|
bsCollapse.show();
|
||||||
|
} else if (!hasVisibleResults) {
|
||||||
|
bsCollapse.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Loading…
x
Reference in New Issue
Block a user