Files
ihrm/project/cbv/tasks.py
2026-01-13 14:45:17 +05:30

608 lines
21 KiB
Python

"""
This page handles the cbv methods for task page
"""
import logging
from typing import Any
from django import forms
from django.contrib import messages
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from base.methods import get_subordinates
from horilla_views.cbv_methods import login_required
from horilla_views.generic.cbv.views import (
HorillaCardView,
HorillaDetailedView,
HorillaFormView,
HorillaListView,
HorillaNavView,
TemplateView,
)
from project.cbv.project_stage import StageDynamicCreateForm
from project.cbv.projects import DynamicProjectCreationFormView
from project.filters import TaskAllFilter
from project.forms import TaskAllForm
from project.methods import you_dont_have_permission
from project.models import Project, ProjectStage, Task
from project.templatetags.taskfilters import task_crud_perm
logger = logging.getLogger(__name__)
@method_decorator(login_required, name="dispatch")
class TasksTemplateView(TemplateView):
"""
view page of the task page
"""
template_name = "cbv/tasks/task_template_view.html"
@method_decorator(login_required, name="dispatch")
class TaskListView(HorillaListView):
"""
list view of the page
"""
model = Task
filter_class = TaskAllFilter
action_method = "actions"
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.view_id = "task-list-container"
self.search_url = reverse("tasks-list-view")
def get_queryset(self):
queryset = super().get_queryset()
active = (
True
if self.request.GET.get("is_active", True)
in ["unknown", "True", "true", True]
else False
)
queryset = queryset.filter(is_active=active)
if not self.request.user.has_perm("project.view_task"):
employee_id = self.request.user.employee_get
subordinates = get_subordinates(self.request)
subordinate_ids = [subordinate.id for subordinate in subordinates]
project = queryset.filter(
Q(project__managers=employee_id)
| Q(project__members=employee_id)
| Q(project__managers__in=subordinate_ids)
| Q(project__members__in=subordinate_ids)
)
queryset = (
queryset.filter(
Q(task_members=employee_id)
| Q(task_managers=employee_id)
| Q(task_members__in=subordinate_ids)
| Q(task_managers__in=subordinate_ids)
)
| project
)
return queryset.distinct()
@cached_property
def columns(self):
get_field = self.model()._meta.get_field
return [
(get_field("title").verbose_name, "title"),
(get_field("project").verbose_name, "project"),
(get_field("stage").verbose_name, "stage"),
(get_field("task_managers").verbose_name, "get_managers"),
(get_field("task_members").verbose_name, "get_members"),
(get_field("end_date").verbose_name, "end_date"),
(get_field("status").verbose_name, "get_status_display"),
(get_field("description").verbose_name, "get_description"),
]
@cached_property
def sortby_mapping(self):
get_field = self.model()._meta.get_field
return [
(get_field("title").verbose_name, "title"),
(get_field("project").verbose_name, "project__title"),
(get_field("stage").verbose_name, "stage"),
(get_field("end_date").verbose_name, "end_date"),
(get_field("status").verbose_name, "status"),
]
row_status_indications = [
(
"todo--dot",
_("To Do"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('to_do');
$('#applyFilter').click();
"
""",
),
(
"in-progress--dot",
_("In progress"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('in_progress');
$('#applyFilter').click();
"
""",
),
(
"completed--dot",
_("Completed"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('completed');
$('#applyFilter').click();
"
""",
),
(
"expired--dot",
_("Expired"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('expired');
$('#applyFilter').click();
"
""",
),
]
row_status_class = "status-{status}"
row_attrs = """
hx-get='{task_detail_view}?instance_ids={ordered_ids}'
hx-target="#genericModalBody"
data-target="#genericModal"
data-toggle="oh-modal-toggle"
"""
@method_decorator(login_required, name="dispatch")
class TasksNavBar(HorillaNavView):
"""
navbar of teh page
"""
group_by_fields = [
"project",
"stage",
"status",
]
filter_form_context_name = "form"
filter_instance = TaskAllFilter()
search_swap_target = "#listContainer"
filter_body_template = "cbv/tasks/task_filter.html"
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.search_url = reverse("tasks-list-view")
self.view_types = [
{
"type": "list",
"icon": "list-outline",
"url": reverse("tasks-list-view"),
"attrs": f"""
title ='{_("List")}'
""",
},
{
"type": "card",
"icon": "grid-outline",
"url": reverse("tasks-card-view"),
"attrs": f"""
title ='{_("Card")}'
""",
},
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
employee = self.request.user.employee_get
projects = Project.objects.all()
managers = [
manager for project in projects for manager in project.managers.all()
]
if employee in managers or self.request.user.has_perm("project.add_task"):
self.create_attrs = f"""
onclick = "event.stopPropagation();"
data-toggle="oh-modal-toggle"
data-target="#genericModal"
hx-target="#genericModalBody"
hx-get="{reverse('create-task-all')}"
"""
if self.request.user.has_perm("project.view_task"):
self.actions = [
{
"action": _("Archive"),
"attrs": """
id="archiveTask",
style="cursor: pointer;"
""",
},
{
"action": _("Un-Archive"),
"attrs": """
id="unArchiveTask",
style="cursor: pointer;"
""",
},
{
"action": _("Delete"),
"attrs": """
class="oh-dropdown__link--danger"
data-action = "delete"
id="deleteTask"
style="cursor: pointer; color:red !important"
""",
},
]
context["actions"] = self.actions
context["create_attrs"] = self.create_attrs
return context
@method_decorator(login_required, name="dispatch")
class TaskCreateForm(HorillaFormView):
"""
Form view for create and update tasks
"""
model = Task
form_class = TaskAllForm
template_name = "cbv/tasks/task_form.html"
new_display_title = _("Create") + " " + model._meta.verbose_name
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
if self.request.user.has_perm("project.view_task"):
self.dynamic_create_fields = [
("project", DynamicProjectCreationFormView),
("stage", StageDynamicCreateForm, ["project"]),
]
def get(self, request, *args, pk=None, **kwargs):
project_id = self.kwargs.get("project_id")
stage_id = self.kwargs.get("stage_id")
task_id = self.kwargs.get("pk")
if project_id:
project = Project.objects.filter(id=project_id).first()
elif stage_id:
project = ProjectStage.objects.filter(id=stage_id).first().project
elif task_id:
task = Task.objects.filter(id=task_id).first()
project = task.project
elif not task_id:
return super().get(request, *args, pk=pk, **kwargs)
if (
request.user.employee_get in project.managers.all()
or request.user.is_superuser
or request.user.has_perm("project.add_task")
):
self.dynamic_create_fields = [
("project", DynamicProjectCreationFormView),
("stage", StageDynamicCreateForm),
]
return super().get(request, *args, pk=pk, **kwargs)
elif task_id:
if request.user.employee_get in task.task_managers.all():
return super().get(request, *args, pk=pk, **kwargs)
else:
return you_dont_have_permission(request)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
project_id = self.kwargs.get("project_id")
stage_id = self.kwargs.get("stage_id")
task_id = self.kwargs.get("pk")
dynamic_project_id = self.request.GET.get("dynamic_project")
if dynamic_project_id and dynamic_project_id != "dynamic_create":
stages = ProjectStage.objects.filter(project=dynamic_project_id)
attrs = self.form.fields["stage"].widget.attrs
attrs["style"] = "width:100% !important;"
self.form.fields["stage"].choices = (
[("", _("Select Stage"))]
+ [(stage.pk, stage) for stage in stages]
+ [("dynamic_create", _("Dynamic Create"))]
)
if task_id and not dynamic_project_id:
task = self.form.instance
stages = task.project.project_stages.all()
self.form.fields["stage"].choices = (
[("", _("Select Stage"))]
+ [(stage.pk, stage) for stage in stages]
+ [("dynamic_create", _("Dynamic Create"))]
)
if stage_id:
stage = ProjectStage.objects.filter(id=stage_id).first()
project = stage.project
self.form.fields["stage"].initial = stage
self.form.fields["stage"].choices = [(stage.id, stage.title)]
self.form.fields["project"].initial = project
self.form.fields["project"].choices = [(project.id, project.title)]
elif project_id:
project = Project.objects.get(id=project_id)
self.form.fields["project"].initial = project
self.form.fields["project"].choices = [(project.id, project.title)]
stages = ProjectStage.objects.filter(project=project)
self.form.fields["stage"].choices = [
(stage.id, stage.title) for stage in stages
]
elif self.form.instance.pk:
self.form_class.verbose_name = _("Update Task")
if self.request.GET.get("project_task"):
self.form.fields["project"].widget = forms.HiddenInput()
self.form.fields["stage"].widget = forms.HiddenInput()
else:
if self.request.user.is_superuser:
self.dynamic_create_fields = [
("project", DynamicProjectCreationFormView),
("stage", StageDynamicCreateForm, ["project"]),
]
if project_id or stage_id:
if (
self.request.user.employee_get in project.managers.all()
or self.request.user.is_superuser
):
self.form.fields["project"].choices.append(
("dynamic_create", "Dynamic create")
)
self.form.fields["stage"].choices.append(
("dynamic_create", "Dynamic create")
)
return context
def form_valid(self, form: TaskAllForm) -> HttpResponse:
stage_id = self.kwargs.get("stage_id")
if form.is_valid():
if form.instance.pk:
message = _(f"{self.form.instance} Updated")
else:
message = _("New Task created")
form.save()
messages.success(self.request, _(message))
if stage_id or self.request.GET.get("project_task"):
return HttpResponse("<script>location.reload();</script>")
return self.HttpResponse("<script>$('#applyFilter').click();</script>")
return super().form_valid(form)
class DynamicTaskCreateFormView(TaskCreateForm):
is_dynamic_create_view = True
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.request.GET:
project_id = self.request.GET.get("project_id")
if project_id:
project = Project.objects.get(id=project_id)
stages = ProjectStage.objects.filter(project__id=project_id)
self.form.fields["project"].initial = project
self.form.fields["project"].choices = [(project.id, project.title)]
self.form.fields["stage"].queryset = stages
# self.form.fields["project"].widget = forms.HiddenInput()
return context
@method_decorator(login_required, name="dispatch")
class TaskDetailView(HorillaDetailedView):
"""
detail view of the task page
"""
model = Task
title = _("Task Details")
action_method = "detail_view_actions"
header = {"title": "title", "subtitle": "project", "avatar": "get_avatar"}
@cached_property
def body(self):
get_field = self.model()._meta.get_field
return [
(get_field("project").verbose_name, "project"),
(get_field("stage").verbose_name, "stage"),
(get_field("task_managers").verbose_name, "get_managers"),
(get_field("task_members").verbose_name, "get_members"),
(get_field("status").verbose_name, "get_status_display"),
(get_field("end_date").verbose_name, "end_date"),
(get_field("document").verbose_name, "document_col", True),
(get_field("description").verbose_name, "description"),
]
cols = {
"get_managers": 12,
"get_members": 12,
"description": 12,
}
@method_decorator(login_required, name="dispatch")
class TaskCardView(HorillaCardView):
"""
card view of the page
"""
model = Task
filter_class = TaskAllFilter
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.view_id = "task-card"
self.search_url = reverse("tasks-card-view")
self.actions = [
{
"action": _("Edit"),
"accessibility": "project.cbv.accessibility.task_crud_accessibility",
"attrs": """
data-toggle = "oh-modal-toggle"
data-target = "#genericModal"
hx-target="#genericModalBody"
hx-get ='{get_update_url}'
class="oh-dropdown__link"
style="cursor: pointer;"
""",
},
{
"action": _("archive_status"),
"accessibility": "project.cbv.accessibility.task_crud_accessibility",
"attrs": """
href="{get_archive_url}"
onclick="return confirm('Do you want to {archive_status} this task?')"
class="oh-dropdown__link"
""",
},
{
"action": _("Delete"),
"accessibility": "project.cbv.accessibility.task_crud_accessibility",
"attrs": """
onclick="
event.stopPropagation()
deleteItem({get_delete_url});
"
class="oh-dropdown__link oh-dropdown__link--danger"
""",
},
]
def get_queryset(self):
queryset = super().get_queryset()
active = (
True
if self.request.GET.get("is_active", True)
in ["unknown", "True", "true", True]
else False
)
queryset = queryset.filter(is_active=active)
if not self.request.user.has_perm("project.view_task"):
employee_id = self.request.user.employee_get
subordinates = get_subordinates(self.request)
subordinate_ids = [subordinate.id for subordinate in subordinates]
project = queryset.filter(
Q(project__managers=employee_id)
| Q(project__members=employee_id)
| Q(project__managers__in=subordinate_ids)
| Q(project__members__in=subordinate_ids)
)
queryset = (
queryset.filter(
Q(task_members=employee_id)
| Q(task_managers=employee_id)
| Q(task_members__in=subordinate_ids)
| Q(task_managers__in=subordinate_ids)
)
| project
)
return queryset.distinct()
details = {
"image_src": "get_avatar",
"title": "{title}",
"subtitle": "{card_view_subtitle}",
}
card_attrs = """
hx-get='{task_detail_view}?instance_ids={ordered_ids}'
hx-target="#genericModalBody"
data-target="#genericModal"
data-toggle="oh-modal-toggle"
"""
card_status_indications = [
(
"todo--dot",
_("To Do"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('to_do');
$('#applyFilter').click();
"
""",
),
(
"in-progress--dot",
_("In progress"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('in_progress');
$('#applyFilter').click();
"
""",
),
(
"completed--dot",
_("Completed"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('completed');
$('#applyFilter').click();
"
""",
),
(
"expired--dot",
_("Expired"),
"""
onclick="
$('#applyFilter').closest('form').find('[name=status]').val('expired');
$('#applyFilter').click();
"
""",
),
]
card_status_class = "status-{status}"
@method_decorator(login_required, name="dispatch")
class TasksInIndividualView(TaskListView):
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
employee_id = self.request.GET.get("employee_id")
self.row_attrs = f"""
hx-get='{{task_detail_view}}?instance_ids={{ordered_ids}}&employee_id={employee_id}'
hx-target="#genericModalBody"
data-target="#genericModal"
data-toggle="oh-modal-toggle"
"""
def get_queryset(self):
queryset = super().get_queryset()
employee_id = self.request.GET.get("employee_id")
project_id = self.request.GET.get("project_id")
queryset = queryset.filter(
Q(task_members=employee_id) | Q(task_managers=employee_id)
)
queryset = queryset.filter(project=project_id).distinct()
return queryset
sortby_mapping = []
header_attrs = {
"title": """ style="width: 150px !important;" """,
}
show_filter_tags = False
row_status_indications = None
bulk_select_option = False
action_method = None