"""
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()
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)
employee = self.request.user.employee_get
projects = Project.objects.all()
managers = [
manager for project in projects for manager in project.managers.all()
]
members = [member for project in projects for member in project.members.all()]
self.search_url = reverse("tasks-list-view")
if employee in managers + members 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')}"
"""
self.view_types = [
{
"type": "list",
"icon": "list-outline",
"url": reverse("tasks-list-view"),
"attrs": """
title ='List'
""",
},
{
"type": "card",
"icon": "grid-outline",
"url": reverse("tasks-card-view"),
"attrs": """
title ='Card'
""",
},
]
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"
""",
},
]
@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")
try:
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
):
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)
except Exception as e:
logger.error(e)
messages.error(request, _("Something went wrong!"))
return HttpResponse("")
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("")
return self.HttpResponse("")
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("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("status").verbose_name, "get_status_display"),
(get_field("end_date").verbose_name, "end_date"),
(get_field("description").verbose_name, "description"),
(get_field("document").verbose_name, "document_col", True),
]
@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()
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": "Project Name : {if_project}
Stage Name : {stage}
End Date : {end_date}",
}
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}"
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 = HorillaListView.get_queryset(self)
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_manager=employee_id)
)
queryset = queryset.filter(project=project_id)
return queryset
row_status_indications = None
bulk_select_option = None
action_method = None