update
This commit is contained in:
parent
7d93bfde9f
commit
fe0f0d836d
@ -1,3 +1,5 @@
|
|||||||
|
from django.contrib.auth.models import Permission
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
from appointment.models import Appointment, Service, StaffMember
|
from appointment.models import Appointment, Service, StaffMember
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django_countries.widgets import CountrySelectWidget
|
from django_countries.widgets import CountrySelectWidget
|
||||||
@ -896,3 +898,27 @@ class OpportunityStatusForm(forms.Form):
|
|||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class GroupForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Group
|
||||||
|
fields = ["name"]
|
||||||
|
|
||||||
|
class PermissionForm(forms.ModelForm):
|
||||||
|
name = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Permission.objects.filter(content_type__app_label='inventory'),
|
||||||
|
widget=forms.CheckboxSelectMultiple(),
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
class Meta:
|
||||||
|
model = Permission
|
||||||
|
fields = ["name"]
|
||||||
|
|
||||||
|
class UserGroupForm(forms.ModelForm):
|
||||||
|
name = forms.ModelMultipleChoiceField(
|
||||||
|
queryset= Group.objects.all(),
|
||||||
|
widget=forms.CheckboxSelectMultiple(),
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
class Meta:
|
||||||
|
model = Group
|
||||||
|
fields = ["name"]
|
||||||
@ -54,7 +54,6 @@ class InjectDealerMiddleware:
|
|||||||
try:
|
try:
|
||||||
dealer = get_user_type(request)
|
dealer = get_user_type(request)
|
||||||
request.user.dealer = dealer
|
request.user.dealer = dealer
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
|
|||||||
@ -938,6 +938,13 @@ class Staff(models.Model, LocalizedNameMixin):
|
|||||||
|
|
||||||
objects = StaffUserManager()
|
objects = StaffUserManager()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user(self):
|
||||||
|
return self.staff_member.user
|
||||||
|
|
||||||
|
@property
|
||||||
|
def groups(self):
|
||||||
|
return self.staff_member.user.groups
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Staff")
|
verbose_name = _("Staff")
|
||||||
verbose_name_plural = _("Staff")
|
verbose_name_plural = _("Staff")
|
||||||
|
|||||||
@ -336,6 +336,14 @@ urlpatterns = [
|
|||||||
path("user/<int:pk>/", views.UserDetailView.as_view(), name="user_detail"),
|
path("user/<int:pk>/", views.UserDetailView.as_view(), name="user_detail"),
|
||||||
path("user/", views.UserListView.as_view(), name="user_list"),
|
path("user/", views.UserListView.as_view(), name="user_list"),
|
||||||
path("user/<int:pk>/confirm/", views.UserDeleteview, name="user_delete"),
|
path("user/<int:pk>/confirm/", views.UserDeleteview, name="user_delete"),
|
||||||
|
path("user/<int:pk>/groups/", views.UserGroupView, name="user_groups"),
|
||||||
|
# Group URLs
|
||||||
|
path("group/create/", views.GroupCreateView.as_view(), name="group_create"),
|
||||||
|
path("group/<int:pk>/update/", views.GroupUpdateView.as_view(), name="group_update"),
|
||||||
|
path("group/<int:pk>/", views.GroupDetailView.as_view(), name="group_detail"),
|
||||||
|
path("group/", views.GroupListView.as_view(), name="group_list"),
|
||||||
|
path("group/<int:pk>/confirm/", views.GroupDeleteview, name="group_delete"),
|
||||||
|
path("group/<int:pk>/permission/", views.GroupPermissionView, name="group_permission"),
|
||||||
# Organization URLs
|
# Organization URLs
|
||||||
path(
|
path(
|
||||||
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
|
"organizations/", views.OrganizationListView.as_view(), name="organization_list"
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
from django.db.models import Func
|
from django.db.models import Func
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
|
from appointment.models import Appointment,AppointmentRequest,Service,StaffMember
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from calendar import month_name
|
from calendar import month_name
|
||||||
@ -1845,8 +1846,142 @@ def delete_vendor(request, pk):
|
|||||||
# slug_field = "order_id"
|
# slug_field = "order_id"
|
||||||
# slug_url_kwarg = "order_id"
|
# slug_url_kwarg = "order_id"
|
||||||
|
|
||||||
|
#group
|
||||||
|
class GroupListView(LoginRequiredMixin, ListView):
|
||||||
|
model = Group
|
||||||
|
context_object_name = "groups"
|
||||||
|
paginate_by = 10
|
||||||
|
template_name = "groups/group_list.html"
|
||||||
|
|
||||||
|
# def get_queryset(self):
|
||||||
|
# query = self.request.GET.get("q")
|
||||||
|
# dealer = get_user_type(self.request)
|
||||||
|
# staff = models.Staff.objects.filter(dealer=dealer).all()
|
||||||
|
# return apply_search_filters(staff, query)
|
||||||
|
|
||||||
|
class GroupDetailView(LoginRequiredMixin, DetailView):
|
||||||
|
model = Group
|
||||||
|
template_name = "groups/group_detail.html"
|
||||||
|
context_object_name = "group"
|
||||||
|
|
||||||
|
|
||||||
|
class GroupCreateView(
|
||||||
|
LoginRequiredMixin,
|
||||||
|
SuccessMessageMixin,
|
||||||
|
CreateView,
|
||||||
|
):
|
||||||
|
model = Group
|
||||||
|
form_class = forms.GroupForm
|
||||||
|
template_name = "groups/group_form.html"
|
||||||
|
success_url = reverse_lazy("group_list")
|
||||||
|
success_message = _("Group created successfully.")
|
||||||
|
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# dealer = get_user_type(self.request)
|
||||||
|
|
||||||
|
# email = form.cleaned_data["email"]
|
||||||
|
# password = "Tenhal@123"
|
||||||
|
# user = User.objects.create_user(username=form.cleaned_data["name"], email=email, password=password)
|
||||||
|
# user.is_staff = True
|
||||||
|
# user.save()
|
||||||
|
# staff_member = StaffMember.objects.create(user=user)
|
||||||
|
# services = form.cleaned_data["service_offered"]
|
||||||
|
# if services:
|
||||||
|
# for service in services:
|
||||||
|
# staff_member.services_offered.add(service)
|
||||||
|
# staff = form.save(commit=False)
|
||||||
|
# staff.staff_member = staff_member
|
||||||
|
# staff.dealer = dealer
|
||||||
|
# staff.save()
|
||||||
|
# return super().form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
|
class GroupUpdateView(
|
||||||
|
LoginRequiredMixin,
|
||||||
|
SuccessMessageMixin,
|
||||||
|
UpdateView,
|
||||||
|
):
|
||||||
|
model = Group
|
||||||
|
form_class = forms.GroupForm
|
||||||
|
template_name = "groups/group_form.html"
|
||||||
|
success_url = reverse_lazy("group_list")
|
||||||
|
success_message = _("Group updated successfully.")
|
||||||
|
|
||||||
|
# def get_form_kwargs(self):
|
||||||
|
# kwargs = super().get_form_kwargs()
|
||||||
|
# kwargs["instance"] = self.get_object() # Pass the Staff instance to the form
|
||||||
|
# return kwargs
|
||||||
|
|
||||||
|
# def get_form(self, form_class = None):
|
||||||
|
# form = super().get_form(form_class)
|
||||||
|
# form.fields['email'].disabled = True
|
||||||
|
# return form
|
||||||
|
# def get_initial(self):
|
||||||
|
# initial = super().get_initial()
|
||||||
|
# initial['service_offered'] = self.object.staff_member.services_offered.all()
|
||||||
|
# initial['email'] = self.object.staff_member.user.email
|
||||||
|
# return initial
|
||||||
|
# def form_valid(self, form):
|
||||||
|
# services = form.cleaned_data["service_offered"]
|
||||||
|
# if not services:
|
||||||
|
# self.object.staff_member.services_offered.clear()
|
||||||
|
# else:
|
||||||
|
# for service in services:
|
||||||
|
# self.object.staff_member.services_offered.add(service)
|
||||||
|
|
||||||
|
# staff = form.save(commit=False)
|
||||||
|
# staff.name = form.cleaned_data["name"]
|
||||||
|
# staff.arabic_name = form.cleaned_data["arabic_name"]
|
||||||
|
# staff.phone_number = form.cleaned_data["phone_number"]
|
||||||
|
# staff.staff_type = form.cleaned_data["staff_type"]
|
||||||
|
# staff.save()
|
||||||
|
# return super().form_valid(form)
|
||||||
|
|
||||||
|
def GroupDeleteview(request, pk):
|
||||||
|
group = get_object_or_404(Group, pk=pk)
|
||||||
|
group.delete()
|
||||||
|
messages.success(request, _("Group deleted successfully."))
|
||||||
|
return redirect("group_list")
|
||||||
|
|
||||||
|
def GroupPermissionView(request, pk):
|
||||||
|
group = get_object_or_404(Group, pk=pk)
|
||||||
|
if request.method == "POST":
|
||||||
|
form = forms.PermissionForm(request.POST)
|
||||||
|
group.permissions.clear()
|
||||||
|
permissions = request.POST.getlist("name")
|
||||||
|
|
||||||
|
for i in permissions:
|
||||||
|
try:
|
||||||
|
group.permissions.add(Permission.objects.get(id=int(i)))
|
||||||
|
except Permission.DoesNotExist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
messages.success(request, _("Permission added successfully."))
|
||||||
|
return redirect("group_detail", pk=group.pk)
|
||||||
|
|
||||||
|
form = forms.PermissionForm(initial={"name": group.permissions.all()})
|
||||||
|
return render(request,"groups/group_permission_form.html",{"group": group, "form": form})
|
||||||
|
|
||||||
# Users
|
# Users
|
||||||
|
|
||||||
|
def UserGroupView(request, pk):
|
||||||
|
staff = get_object_or_404(models.Staff, pk=pk)
|
||||||
|
if request.method == "POST":
|
||||||
|
form = forms.UserGroupForm(request.POST)
|
||||||
|
groups = request.POST.getlist("name")
|
||||||
|
staff.groups.clear()
|
||||||
|
for i in groups:
|
||||||
|
try:
|
||||||
|
staff.groups.add(Group.objects.get(id=int(i)))
|
||||||
|
except Group.DoesNotExist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
messages.success(request, _("Group added successfully."))
|
||||||
|
return redirect("user_detail", pk=staff.pk)
|
||||||
|
|
||||||
|
form = forms.UserGroupForm(initial={"name": staff.user.groups.all()})
|
||||||
|
return render(request,"users/user_group_form.html",{"staff": staff, "form": form})
|
||||||
|
|
||||||
class UserListView(LoginRequiredMixin, ListView):
|
class UserListView(LoginRequiredMixin, ListView):
|
||||||
model = models.Staff
|
model = models.Staff
|
||||||
context_object_name = "users"
|
context_object_name = "users"
|
||||||
@ -1885,14 +2020,15 @@ class UserCreateView(
|
|||||||
user = User.objects.create_user(username=form.cleaned_data["name"], email=email, password=password)
|
user = User.objects.create_user(username=form.cleaned_data["name"], email=email, password=password)
|
||||||
user.is_staff = True
|
user.is_staff = True
|
||||||
user.save()
|
user.save()
|
||||||
staff_member = StaffMember.objects.create(user=user)
|
staff_member = StaffMember.objects.create(user=user)
|
||||||
services = form.cleaned_data["service_offered"]
|
for service in form.cleaned_data["service_offered"]:
|
||||||
if services:
|
staff_member.services_offered.add(service)
|
||||||
for service in services:
|
|
||||||
staff_member.services_offered.add(service)
|
|
||||||
staff = form.save(commit=False)
|
staff = form.save(commit=False)
|
||||||
staff.staff_member = staff_member
|
staff.staff_member = staff_member
|
||||||
staff.dealer = dealer
|
staff.dealer = dealer
|
||||||
|
group = Group.objects.filter(name__iexact=staff.staff_type).first()
|
||||||
|
if group:
|
||||||
|
staff.groups.add(group)
|
||||||
staff.save()
|
staff.save()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
@ -1919,8 +2055,8 @@ class UserUpdateView(
|
|||||||
return form
|
return form
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
initial['service_offered'] = self.object.staff_member.services_offered.all()
|
|
||||||
initial['email'] = self.object.staff_member.user.email
|
initial['email'] = self.object.staff_member.user.email
|
||||||
|
initial['service_offered'] = self.object.staff_member.services_offered.all()
|
||||||
return initial
|
return initial
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
services = form.cleaned_data["service_offered"]
|
services = form.cleaned_data["service_offered"]
|
||||||
@ -1934,12 +2070,13 @@ class UserUpdateView(
|
|||||||
staff.name = form.cleaned_data["name"]
|
staff.name = form.cleaned_data["name"]
|
||||||
staff.arabic_name = form.cleaned_data["arabic_name"]
|
staff.arabic_name = form.cleaned_data["arabic_name"]
|
||||||
staff.phone_number = form.cleaned_data["phone_number"]
|
staff.phone_number = form.cleaned_data["phone_number"]
|
||||||
staff.staff_type = form.cleaned_data["staff_type"]
|
staff.staff_type = form.cleaned_data["staff_type"]
|
||||||
staff.save()
|
staff.save()
|
||||||
return super().form_valid(form)
|
return super().form_valid(form)
|
||||||
|
|
||||||
def UserDeleteview(request, pk):
|
def UserDeleteview(request, pk):
|
||||||
user = get_object_or_404(models.Staff, pk=pk)
|
user = get_object_or_404(models.Staff, pk=pk)
|
||||||
|
user.staff_member.delete()
|
||||||
user.delete()
|
user.delete()
|
||||||
messages.success(request, _("User deleted successfully."))
|
messages.success(request, _("User deleted successfully."))
|
||||||
return redirect("user_list")
|
return redirect("user_list")
|
||||||
|
|||||||
119
templates/groups/group_detail.html
Normal file
119
templates/groups/group_detail.html
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{{ _("View Group") }}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Delete Modal -->
|
||||||
|
<div class="modal fade" id="deleteModal"
|
||||||
|
data-bs-backdrop="static"
|
||||||
|
data-bs-keyboard="false"
|
||||||
|
tabindex="-1"
|
||||||
|
aria-labelledby="deleteModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-sm ">
|
||||||
|
<div class="modal-content rounded">
|
||||||
|
<div class="modal-body d-flex justify-content-center">
|
||||||
|
<h1 class="text-danger me-2"><i class="bi bi-exclamation-diamond-fill"></i></h1>
|
||||||
|
<span class="text-danger">
|
||||||
|
{% trans "Are you sure you want to delete this group?" %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-secondary"
|
||||||
|
data-bs-dismiss="modal">
|
||||||
|
{% trans 'No' %}
|
||||||
|
</button>
|
||||||
|
<a type="button"
|
||||||
|
class="btn btn-sm btn-danger"
|
||||||
|
href="{% url 'group_delete' group.id %}">
|
||||||
|
{% trans 'Yes' %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row my-5">
|
||||||
|
<div class="card rounded ">
|
||||||
|
<div class="card-header ">
|
||||||
|
<p class="mb-0">{{ _("Group Details") }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<p><strong>{{ _("Name") }}:</strong> {{ group.name }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<table class="table table-hover table-responsive-sm fs-9 mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><h4>{% trans 'Users'|capfirst %}</h4></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in group.user_set.all %}
|
||||||
|
<tr>
|
||||||
|
<td><p><strong>{{ _("Name") }}:</strong> {{ user.staffmember.staff }}</p></td>
|
||||||
|
<td><p><strong>{{ _("Email") }}:</strong> {{ user }}</p></td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td>{% trans "No Permissions" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||||
|
<div class="card-header ">
|
||||||
|
</div>
|
||||||
|
<h4 class="my-4">Permissions</h4>
|
||||||
|
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'group_permission' group.id %}"><i class="fa-solid fa-unlock"></i> Manage Permissions</a>
|
||||||
|
|
||||||
|
<table class="table table-hover table-responsive-sm fs-9 mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans 'name'|capfirst %}</th>
|
||||||
|
<th>{% trans 'Action'|capfirst %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for permission in group.permissions.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ permission.codename }}</td>
|
||||||
|
<td>{{ permission.name }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td>{% trans "No Permissions" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex ">
|
||||||
|
<a class="btn btn-sm btn-primary me-1" href="{% url 'group_update' group.id %}">
|
||||||
|
<i class="fa-solid fa-pen-to-square"></i>
|
||||||
|
{{ _("Edit") }}
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-danger me-1"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#deleteModal">
|
||||||
|
<i class="fa-solid fa-trash"></i>
|
||||||
|
{{ _("Delete") }}
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-sm btn-secondary"
|
||||||
|
href="{% url 'group_list' %}">
|
||||||
|
<i class="fa-solid fa-arrow-left"></i>
|
||||||
|
{% trans "Back to List" %}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
45
templates/groups/group_form.html
Normal file
45
templates/groups/group_form.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% block title %}{% trans "Group" %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="d-sm-flex justify-content-between">
|
||||||
|
|
||||||
|
<h3 class="mb-3">
|
||||||
|
{% if staff.created %}
|
||||||
|
{{ _("Edit Group") }}
|
||||||
|
{% else %}
|
||||||
|
{{ _("Add Group") }}
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
|
||||||
|
<form class="row g-3 mb-9" method="post" class="form" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ redirect_field }}
|
||||||
|
{{ form|crispy }}
|
||||||
|
{% for error in form.errors %}
|
||||||
|
<div class="text-danger">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="d-flex mb-3">
|
||||||
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6"><i class="fa-solid fa-ban"></i> {% trans "cancel"|capfirst %}</a>
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
|
{{ _("Save") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
57
templates/groups/group_list.html
Normal file
57
templates/groups/group_list.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Group" %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<section class="">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="d-md-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
<a href="{% url 'group_create' %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{% trans "Add Group" %}</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||||
|
|
||||||
|
<table class="table table-hover table-responsive-sm fs-9 mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans 'name'|capfirst %}</th>
|
||||||
|
<th>{% trans 'total Users'|capfirst %}</th>
|
||||||
|
<th>{% trans 'total permission'|capfirst %}</th>
|
||||||
|
<th>{% trans 'actions'|capfirst %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for group in groups %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ group.name }}</td>
|
||||||
|
<td><i class="fa-solid fa-users"></i> {{ group.user_set.count }}</td>
|
||||||
|
<td><i class="fa-solid fa-unlock"></i> {{ group.permissions.count }}</td>
|
||||||
|
<td>
|
||||||
|
<a class="btn btn-phoenix-success"
|
||||||
|
href="{% url 'group_detail' group.id %}">
|
||||||
|
<i class="fa-solid fa-eye"></i>
|
||||||
|
{% trans 'view'|capfirst %}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex justify-content-center">
|
||||||
|
{% if is_paginated %}
|
||||||
|
{% include 'partials/pagination.html' %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
45
templates/groups/group_permission_form.html
Normal file
45
templates/groups/group_permission_form.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% block title %}{% trans "Permission" %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="d-sm-flex justify-content-between">
|
||||||
|
|
||||||
|
<h3 class="mb-3">
|
||||||
|
{% if group.created %}
|
||||||
|
{{ _("Edit Permission") }}
|
||||||
|
{% else %}
|
||||||
|
{{ _("Add Permission") }}
|
||||||
|
{% endif %}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
|
||||||
|
<form class="row g-3 mb-9" method="post" class="form" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ redirect_field }}
|
||||||
|
{{ form|crispy }}
|
||||||
|
{% for error in form.errors %}
|
||||||
|
<div class="text-danger">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="d-flex mb-3">
|
||||||
|
<a href="{% url 'group_detail' group.pk %}" class="btn btn-phoenix-primary me-2 px-6"><i class="fa-solid fa-ban"></i> {% trans "cancel"|capfirst %}</a>
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
|
{{ _("Save") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -411,7 +411,7 @@
|
|||||||
<div class="card position-relative border-0">
|
<div class="card position-relative border-0">
|
||||||
<div class="card-body p-0">
|
<div class="card-body p-0">
|
||||||
<div class="text-center pt-4 pb-3">
|
<div class="text-center pt-4 pb-3">
|
||||||
|
|
||||||
<div class="avatar avatar-xl">
|
<div class="avatar avatar-xl">
|
||||||
{% if user.dealer.logo %}
|
{% if user.dealer.logo %}
|
||||||
<img class="rounded-circle" src="{{ user.dealer.logo.url }}" alt="" />
|
<img class="rounded-circle" src="{{ user.dealer.logo.url }}" alt="" />
|
||||||
@ -441,7 +441,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.dealer %}
|
{% if user.dealer %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link px-3 d-block" href="{% url 'user_list' %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff") }}</a>
|
<a class="nav-link px-3 d-block" href="{% url 'user_list' %}"><span class="me-2 text-body align-bottom" data-feather="users"></span>{{ _("Staff & Group") }}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link px-3 d-block" href="{% url 'dealer_activity' %}"> <span class="me-2 text-body align-bottom" data-feather="lock"></span>{{ _("Activity") }}</a>
|
<a class="nav-link px-3 d-block" href="{% url 'dealer_activity' %}"> <span class="me-2 text-body align-bottom" data-feather="lock"></span>{{ _("Activity") }}</a>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<span class="text-danger">
|
<span class="text-danger">
|
||||||
{% trans "Are you sure you want to delete this user?" %}
|
{% trans "Are you sure you want to delete this user?" %}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="btn btn-sm btn-secondary"
|
class="btn btn-sm btn-secondary"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
<div class="row my-5">
|
<div class="row my-5">
|
||||||
<div class="card rounded ">
|
<div class="card rounded ">
|
||||||
<div class="card-header ">
|
<div class="card-header ">
|
||||||
<p class="mb-0">{{ _("User Details") }}</p>
|
<p class="mb-0"><i class="fa-solid fa-user"></i> {{ _("User Details") }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -53,20 +53,45 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="table-responsive scrollbar mx-n1 px-1">
|
||||||
|
<div class="card-header ">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<h4 class="my-4">Groups</h4>
|
||||||
|
<a class="btn btn-sm btn-primary mt-2 mb-4" href="{% url 'user_groups' user_.pk %}"><i class="fa-solid fa-users"></i> Manage Groups</a>
|
||||||
|
<table class="table table-hover table-responsive-sm fs-9 mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans 'name'|capfirst %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for group in user_.groups.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ group }}</td>
|
||||||
|
</tr>
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<td>{% trans "No Group" %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div class="card-footer d-flex ">
|
<div class="card-footer d-flex ">
|
||||||
<a class="btn btn-sm btn-primary me-1" href="{% url 'user_update' user_.id %}">
|
<a class="btn btn-sm btn-primary me-1" href="{% url 'user_update' user_.id %}">
|
||||||
<!--<i class="bi bi-pencil-square"></i> -->
|
<i class="fa-solid fa-pen-to-square"></i>
|
||||||
{{ _("Edit") }}
|
{{ _("Edit") }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-sm btn-danger me-1"
|
<a class="btn btn-sm btn-danger me-1"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#deleteModal">
|
data-bs-target="#deleteModal">
|
||||||
<!--<i class="bi bi-trash-fill"></i>-->
|
<i class="fa-solid fa-trash"></i>
|
||||||
{{ _("Delete") }}
|
{{ _("Delete") }}
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-sm btn-secondary"
|
<a class="btn btn-sm btn-secondary"
|
||||||
href="{% url 'user_list' %}">
|
href="{% url 'user_list' %}">
|
||||||
<!--<i class="bi bi-arrow-left-square-fill"></i>-->
|
<i class="fa-regular fa-circle-left"></i>
|
||||||
{% trans "Back to List" %}
|
{% trans "Back to List" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
<div class="d-sm-flex justify-content-between">
|
<div class="d-sm-flex justify-content-between">
|
||||||
|
|
||||||
<h3 class="mb-3">
|
<h3 class="mb-3">
|
||||||
|
<i class="fa-solid fa-user-tie"></i>
|
||||||
{% if staff.created %}
|
{% if staff.created %}
|
||||||
{{ _("Edit Staff") }}
|
{{ _("Edit Staff") }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@ -32,9 +33,9 @@
|
|||||||
<div class="text-danger">{{ error }}</div>
|
<div class="text-danger">{{ error }}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="d-flex mb-3">
|
<div class="d-flex mb-3">
|
||||||
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6">{% trans "cancel"|capfirst %}</a>
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6"><i class="fa-solid fa-ban"></i> {% trans "cancel"|capfirst %}</a>
|
||||||
<button class="btn btn-primary" type="submit">
|
<button class="btn btn-primary" type="submit">
|
||||||
<!--<i class="bi bi-save"></i> -->
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
{{ _("Save") }}
|
{{ _("Save") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
38
templates/users/user_group_form.html
Normal file
38
templates/users/user_group_form.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% block title %}{% trans "Group" %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="d-sm-flex justify-content-between">
|
||||||
|
<h3 class="mb-3"><i class="fa-solid fa-users"></i> {{ _("Manage Groups") }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
|
||||||
|
<form class="row g-3 mb-9" method="post" class="form" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ redirect_field }}
|
||||||
|
{{ form|crispy }}
|
||||||
|
{% for error in form.errors %}
|
||||||
|
<div class="text-danger">{{ error }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
<div class="d-flex mb-3">
|
||||||
|
<a href="{{request.META.HTTP_REFERER}}" class="btn btn-phoenix-primary me-2 px-6"><i class="fa-solid fa-ban"></i> {% trans "cancel"|capfirst %}</a>
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
|
<i class="fa-solid fa-floppy-disk"></i>
|
||||||
|
{{ _("Save") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -11,8 +11,8 @@
|
|||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<div class="d-md-flex justify-content-between">
|
<div class="d-md-flex justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><span class="fas fa-plus me-2"></span>{% trans "Add Staff" %}</a>
|
<a href="{% url 'user_create' %}" class="btn btn-sm btn-phoenix-primary"><i class="fa-solid fa-user-tie"></i> {% trans "Add New Staff" %}</a>
|
||||||
|
<a href="{% url 'group_list' %}" class="btn btn-sm btn-phoenix-success"><i class="fa-solid fa-user-group"></i> {% trans "Manage Groups & Permissions" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -25,6 +25,7 @@
|
|||||||
<th>{% trans 'arabic name'|capfirst %}</th>
|
<th>{% trans 'arabic name'|capfirst %}</th>
|
||||||
<th>{% trans 'phone number'|capfirst %}</th>
|
<th>{% trans 'phone number'|capfirst %}</th>
|
||||||
<th>{% trans 'role'|capfirst %}</th>
|
<th>{% trans 'role'|capfirst %}</th>
|
||||||
|
<th>{% trans 'groups'|capfirst %}</th>
|
||||||
<th>{% trans 'actions'|capfirst %}</th>
|
<th>{% trans 'actions'|capfirst %}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -34,10 +35,18 @@
|
|||||||
<td>{{ user.name }}</td>
|
<td>{{ user.name }}</td>
|
||||||
<td>{{ user.arabic_name }}</td>
|
<td>{{ user.arabic_name }}</td>
|
||||||
<td>{{ user.phone_number }}</td>
|
<td>{{ user.phone_number }}</td>
|
||||||
<td>{% trans user.staff_type %}</td>
|
<td>
|
||||||
|
<span class="badge badge-sm bg-primary"><i class="fa-solid fa-scroll"></i> {% trans user.staff_type|title %}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for group in user.groups.all %}
|
||||||
|
<span class="badge badge-sm bg-info"><i class="fa-solid fa-user-group"></i> {{ group.name }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn-phoenix-success"
|
<a class="btn btn-phoenix-success"
|
||||||
href="{% url 'user_detail' user.id %}">
|
href="{% url 'user_detail' user.id %}">
|
||||||
|
<i class="fa-solid fa-eye"></i>
|
||||||
{% trans 'view'|capfirst %}
|
{% trans 'view'|capfirst %}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user