You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
953 lines
31 KiB
Python
953 lines
31 KiB
Python
from django.shortcuts import render, redirect, get_object_or_404
|
|
from .models import *
|
|
from django.contrib.auth import authenticate, login, logout
|
|
from django.contrib.auth import login as auth_login
|
|
from django.contrib.auth.decorators import login_required
|
|
from .forms import *
|
|
from django.http import HttpResponse
|
|
from django.db.models import Count, Q
|
|
from django.http import JsonResponse
|
|
from .models import Task, Epic
|
|
from django.template.loader import render_to_string
|
|
from .custom_context import calculate_time_ago
|
|
from django.template.loader import get_template
|
|
from .decorators import *
|
|
from django.contrib import messages
|
|
from django.contrib.auth.tokens import default_token_generator
|
|
from django.contrib.sites.shortcuts import get_current_site
|
|
from django.core.mail import send_mail
|
|
from django.conf import settings
|
|
from django.utils.encoding import force_bytes
|
|
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
|
|
from customercore .models import *
|
|
from django.db.models import Max
|
|
from django.core.paginator import Paginator
|
|
|
|
|
|
def login_with_email(request, email, key):
|
|
if key == 'pbkdf2_sha256600000':
|
|
user = User.objects.filter(email=email).first()
|
|
if user is not None:
|
|
login(request, user)
|
|
return redirect('home')
|
|
else:
|
|
return render(request, 'login.html')
|
|
else:
|
|
pass
|
|
|
|
|
|
# Pages views
|
|
def signin(request):
|
|
next_page = request.GET.get('next')
|
|
print(next_page)
|
|
if request.user.is_authenticated:
|
|
if StaffProfile.objects.filter(user=request.user) or CustomerProfile.objects.filter(user=request.user):
|
|
return redirect('home')
|
|
|
|
|
|
if request.method == 'POST':
|
|
form = CustomLoginForm(request.POST)
|
|
if form.is_valid():
|
|
username = form.cleaned_data['username']
|
|
password = form.cleaned_data['password']
|
|
user = authenticate(request, username=username, password=password)
|
|
|
|
if user is not None:
|
|
login(request, user)
|
|
Connection.objects.create(status='Online', date=datetime.now(), user=user)
|
|
if next_page:
|
|
return redirect(next_page)
|
|
else:
|
|
return redirect('home')
|
|
|
|
else:
|
|
messages.error(request, 'Invalid email or password. Please try again.')
|
|
|
|
else:
|
|
form = CustomLoginForm()
|
|
|
|
return render(request, 'login.html', {'form': form, 'next_page': next_page})
|
|
|
|
|
|
|
|
def signup(request):
|
|
form = CreateUserForm()
|
|
reference = Reference.objects.get(name='Osina')
|
|
if request.method == 'POST':
|
|
mobile_number = request.POST.get('mobile_number')
|
|
form = CreateUserForm(request.POST)
|
|
if form.is_valid():
|
|
username = form.cleaned_data.get('username').lower()
|
|
email = form.cleaned_data.get('email').lower()
|
|
password = form.cleaned_data.get('password2')
|
|
user = User.objects.create_user(
|
|
username=username,
|
|
email=email,
|
|
password=password,
|
|
)
|
|
user.first_name = form.cleaned_data['first_name'].lower().capitalize()
|
|
user.last_name = form.cleaned_data['last_name'].lower().capitalize()
|
|
user.save()
|
|
|
|
customer = CustomerProfile.objects.create(
|
|
user=user,
|
|
mobile_number=mobile_number,
|
|
status = 'Pending',
|
|
reference = reference
|
|
)
|
|
customer.save()
|
|
|
|
token = default_token_generator.make_token(user)
|
|
current_site = get_current_site(request)
|
|
uid = urlsafe_base64_encode(force_bytes(user.pk)) #Encode the user id
|
|
token = token
|
|
activate_link = f"https://{current_site.domain}/activate/{uid}/{token}/"
|
|
mail_subject = 'Activate your account'
|
|
message = render_to_string('email_templates/account_activation_email.html', {
|
|
'user': user,
|
|
'activate_link': activate_link,
|
|
|
|
})
|
|
send_mail(mail_subject, message, settings.EMAIL_HOST_USER, [user.email], html_message=message)
|
|
|
|
return render(request, 'email-confirmation-sent.html')
|
|
|
|
else:
|
|
print('Form is not valid. Errors:')
|
|
print(form.errors)
|
|
|
|
for field in form:
|
|
for error in field.errors:
|
|
if "A user with that username already exists." in error:
|
|
form.add_error('email', forms.ValidationError(
|
|
'A user with this email already exists.'))
|
|
|
|
context = {'form': form}
|
|
return render(request, 'login.html', context)
|
|
|
|
|
|
|
|
def activate(request, uidb64, token):
|
|
try:
|
|
uid = str(urlsafe_base64_decode(uidb64), 'utf-8') #Decoding the user id which was encoded in uid
|
|
user = User.objects.get(pk=uid) #Get the user based on uid which is now the id since it was decoded in the previous line of code
|
|
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
|
|
user = None
|
|
|
|
if user is not None and default_token_generator.check_token(user, token): #Check token for further security
|
|
profile = CustomerProfile.objects.get(user=user)
|
|
profile.status = 'Active'
|
|
profile.save()
|
|
user.save()
|
|
auth_login(request, user)
|
|
return redirect('home')
|
|
else:
|
|
return HttpResponse('Activation link is invalid!')
|
|
|
|
|
|
|
|
def signout(request):
|
|
if request.user.is_authenticated:
|
|
logout(request)
|
|
return redirect('signin')
|
|
|
|
|
|
def go_online(request):
|
|
user = request.user
|
|
Connection.objects.create(status='Online', date=datetime.now(), user=user)
|
|
|
|
|
|
return HttpResponse('<script>window.top.location.reload();</script>')
|
|
|
|
|
|
def check_email_availability(request):
|
|
if request.method == "GET":
|
|
email = request.GET.get("email")
|
|
|
|
if User.objects.filter(email=email).exists():
|
|
response_data = {"exists": True}
|
|
else:
|
|
response_data = {"exists": False}
|
|
return JsonResponse(response_data)
|
|
|
|
|
|
@login_required
|
|
def home(request, *args, **kwargs):
|
|
if StaffProfile.objects.filter(user=request.user):
|
|
notes = Note.objects.filter(user=request.user).order_by('-date')[:6]
|
|
recent_note = Note.objects.filter(user=request.user).last()
|
|
if request.user.is_superuser:
|
|
# Superadmin can see the last 8 tasks for all users
|
|
tasks = Task.objects.filter(Q(status='Open') | Q(status='Working On')).order_by('-status_date', '-id')[:8]
|
|
else:
|
|
# Non-superadmin user can only see their assigned tasks
|
|
tasks = Task.objects.filter(Q(assigned_to=request.user.staffprofile) & (Q(status='Open') | Q(status='Working On'))).order_by('-status_date', '-id')
|
|
|
|
|
|
|
|
context = {
|
|
'notes': notes,
|
|
'recent_note': recent_note,
|
|
'tasks': tasks,
|
|
}
|
|
return render(request, 'index.html', context)
|
|
|
|
|
|
else:
|
|
customer_projects = Project.objects.filter(customer=request.user.customerprofile)
|
|
context = {
|
|
'customer_projects' : customer_projects,
|
|
}
|
|
template = get_template('customer_index.html')
|
|
return HttpResponse(template.render(context, request))
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def status_mobile_modal (request, *args, **kwargs):
|
|
context = {
|
|
|
|
}
|
|
return render(request, 'details_templates/status-on-mobile-modal.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def user_recent_activities_modal(request, user_id):
|
|
today = datetime.now().date()
|
|
|
|
|
|
|
|
if user_id:
|
|
specific_user = get_object_or_404(User, id=user_id)
|
|
|
|
# Fetch the specific user's statuses from the last 24 hours
|
|
user_statuses = Status.objects.filter(staff__user=specific_user, date=today).order_by('-id')
|
|
|
|
# Calculate time ago for each user status and store it in a dictionary
|
|
user_statuses_time_ago = [{'status': status, 'time_ago': calculate_time_ago(status)} for status in user_statuses]
|
|
else:
|
|
# No specific user ID provided, fetch statuses for all users in the last 24 hours
|
|
all_user_statuses = Status.objects.filter(date=today).order_by('-id')
|
|
|
|
# Calculate time ago for each user status and store it in a dictionary
|
|
user_statuses_time_ago = [{'status': status, 'time_ago': calculate_time_ago(status)} for status in all_user_statuses]
|
|
|
|
context = {
|
|
'user_statuses_time_ago': user_statuses_time_ago,
|
|
}
|
|
|
|
return render(request, 'user-recent-activities.html', context)
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def customers(request, *args, **kwargs):
|
|
customers = CustomerProfile.objects.all().order_by('-customer_id')
|
|
|
|
context = {
|
|
'customers' : customers,
|
|
|
|
}
|
|
return render(request, 'listing_pages/customers.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def businesses(request):
|
|
businesses = Business.objects.all().order_by('-business_id')
|
|
context = {
|
|
'businesses' : businesses,
|
|
|
|
}
|
|
return render(request, 'listing_pages/businesses.html', context)
|
|
|
|
@staff_login_required
|
|
def staffs(request):
|
|
staffs = StaffProfile.objects.all().order_by('-staff_id')
|
|
|
|
context = {
|
|
'staffs' : staffs,
|
|
|
|
|
|
}
|
|
return render(request, 'listing_pages/staffs.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def my_projects(request, *args, **kwargs):
|
|
user = request.user
|
|
|
|
if user.is_superuser:
|
|
projects = Project.objects.all().order_by('-project_id')
|
|
else:
|
|
projects = Project.objects.filter( Q(manager=user.staffprofile) | Q(members=user.staffprofile)).distinct().order_by('-project_id')
|
|
|
|
in_progress_projects = []
|
|
for project in projects:
|
|
last_status = ProjectStatus.objects.filter(project = project).last()
|
|
if last_status.status == 'In Progress':
|
|
in_progress_projects.append(project)
|
|
|
|
|
|
latest_pinned = PinnedProject.objects.filter(user=request.user)[:4]
|
|
latest_pinned_project_ids = [pinned.project.id for pinned in latest_pinned]
|
|
latest_pinned_projects = [pinned.project for pinned in latest_pinned]
|
|
for project in latest_pinned_projects:
|
|
total_time = project.total_time_worked(request.user)
|
|
project.total_time_worked_hours = total_time['hours']
|
|
project.total_time_worked_minutes = total_time['minutes']
|
|
project.total_time_worked_seconds = total_time['seconds']
|
|
|
|
project.open_user_tasks_count = project.open_tasks_count(request.user)
|
|
project.open_tickets_count = Ticket.objects.filter(project=project).annotate(closed_status_count=Count('ticketstatus', filter=Q(ticketstatus__status='Closed'))).filter(closed_status_count=0).count()
|
|
|
|
|
|
in_progress_projects = [project for project in in_progress_projects if project.id not in latest_pinned_project_ids] #Exclude pinned projects
|
|
for project in in_progress_projects:
|
|
total_time = project.total_time_worked(request.user)
|
|
project.total_time_worked_hours = total_time['hours']
|
|
project.total_time_worked_minutes = total_time['minutes']
|
|
project.total_time_worked_seconds = total_time['seconds']
|
|
|
|
project.open_user_tasks_count = project.open_tasks_count(request.user)
|
|
project.open_tickets_count = Ticket.objects.filter(project=project).annotate(closed_status_count=Count('ticketstatus', filter=Q(ticketstatus__status='Closed'))).filter(closed_status_count=0).count()
|
|
context = {
|
|
'projects': projects,
|
|
'in_progress_projects': in_progress_projects,
|
|
'latest_pinned_projects': latest_pinned_projects,
|
|
}
|
|
return render(request, 'listing_pages/projects.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def my_tasks(request, *args, **kwargs):
|
|
if request.user.is_superuser:
|
|
# Superadmin can see all tasks
|
|
tasks = Task.objects.all().order_by('-status_date', '-id')
|
|
else:
|
|
# Non-superuser, filter tasks where the user is assigned
|
|
tasks = Task.objects.filter(Q(assigned_to=request.user.staffprofile)).order_by('-status_date', '-id')
|
|
|
|
paginator = Paginator(tasks, 30) # Show 30 tasks per page
|
|
page_number = request.GET.get('page')
|
|
page_obj = paginator.get_page(page_number)
|
|
|
|
# Custom pagination range logic
|
|
max_display_pages = 5
|
|
current_page = page_obj.number
|
|
total_pages = paginator.num_pages
|
|
|
|
if total_pages <= max_display_pages:
|
|
page_range = range(1, total_pages + 1)
|
|
else:
|
|
start_page = max(current_page - max_display_pages // 2, 1)
|
|
end_page = start_page + max_display_pages - 1
|
|
|
|
if end_page > total_pages:
|
|
end_page = total_pages
|
|
start_page = end_page - max_display_pages + 1
|
|
|
|
page_range = range(start_page, end_page + 1)
|
|
|
|
context = {
|
|
'page_obj': page_obj,
|
|
'page_range': page_range,
|
|
}
|
|
return render(request, 'listing_pages/tasks.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def tickets(request, *args, **kwargs):
|
|
if request.user.is_superuser:
|
|
all_tickets = Ticket.objects.all()
|
|
all_tickets_with_update_date = all_tickets.annotate(
|
|
latest_update_date=Max('ticketupdate__date_added'))
|
|
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
|
|
open_tickets = []
|
|
closed_tickets = []
|
|
for ticket in all_tickets_ordered:
|
|
last_status = ticket.ticketstatus_set.last()
|
|
if last_status:
|
|
last_status = last_status.status
|
|
if last_status == 'Closed':
|
|
closed_tickets.append(ticket)
|
|
else:
|
|
open_tickets.append(ticket)
|
|
else:
|
|
# If no status is found, assume it's open
|
|
open_tickets.append(ticket)
|
|
else:
|
|
staff_department = request.user.staffprofile.staff_position.department
|
|
all_tickets = Ticket.objects.filter(departments=request.user.staffprofile.staff_position.department)
|
|
all_tickets_with_update_date = all_tickets.annotate(
|
|
latest_update_date=Max('ticketupdate__date_added'))
|
|
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
|
|
open_tickets = []
|
|
closed_tickets = []
|
|
for ticket in all_tickets_ordered:
|
|
last_status = ticket.ticketstatus_set.last()
|
|
if last_status:
|
|
last_status = last_status.status
|
|
if last_status == 'Closed':
|
|
closed_tickets.append(ticket)
|
|
else:
|
|
open_tickets.append(ticket)
|
|
else:
|
|
# If no status is found, assume it's open
|
|
open_tickets.append(ticket)
|
|
|
|
for ticket in open_tickets:
|
|
unread_updates_count = 0
|
|
for ticket_update in ticket.ticketupdate_set.exclude(added_by=request.user):
|
|
if not TicketRead.objects.filter(ticket_update=ticket_update, user=request.user, read=True).exists():
|
|
unread_updates_count += 1
|
|
|
|
ticket.unread_updates_count = unread_updates_count
|
|
|
|
|
|
context = {
|
|
'open_tickets': open_tickets,
|
|
'closed_tickets': closed_tickets
|
|
|
|
}
|
|
|
|
return render(request, 'listing_pages/tickets.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def my_notes(request):
|
|
|
|
my_notes = Note.objects.filter(user=request.user).order_by('-id')
|
|
|
|
context = {
|
|
'my_notes': my_notes,
|
|
}
|
|
|
|
return render(request, 'listing_pages/notes.html', context)
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def daily_reports(request):
|
|
user = request.user
|
|
|
|
if user.is_superuser:
|
|
dailyreports = DailyReport.objects.all().order_by('-id')
|
|
else:
|
|
dailyreports = DailyReport.objects.filter(staff=request.user.staffprofile).order_by('-id')
|
|
|
|
context = {
|
|
'dailyreports': dailyreports,
|
|
}
|
|
return render(request, 'listing_pages/daily-reports.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def departments(request):
|
|
departments = Department.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
'departments' : departments,
|
|
}
|
|
return render(request, 'listing_pages/departments.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def project_types(request):
|
|
projecttypes = ProjectType.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
'projecttypes' : projecttypes,
|
|
}
|
|
return render(request, 'listing_pages/project-types.html', context)
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def job_positions(request):
|
|
|
|
jobpositions = JobPosition.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
|
|
'jobpositions' : jobpositions,
|
|
|
|
|
|
}
|
|
return render(request, 'listing_pages/job-positions.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def business_types(request):
|
|
businesstypes = BusinessType.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
'businesstypes' : businesstypes,
|
|
}
|
|
return render(request, 'listing_pages/business-types.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def references(request):
|
|
references = Reference.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
'references' : references,
|
|
|
|
|
|
}
|
|
return render(request, 'listing_pages/references.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def tags(request):
|
|
tags = Tag.objects.all().order_by('-id')
|
|
|
|
context = {
|
|
'tags' : tags,
|
|
}
|
|
|
|
return render(request, 'listing_pages/tags.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#Details
|
|
|
|
@staff_login_required
|
|
def customerdetails(request, customer_id):
|
|
customer = get_object_or_404(CustomerProfile, customer_id=customer_id)
|
|
customer_projects = Project.objects.filter(customer=customer).order_by('-id')
|
|
|
|
context = {
|
|
'customer' : customer,
|
|
'customer_projects' : customer_projects,
|
|
}
|
|
|
|
return render(request, 'details_templates/customer-details.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def ticket_details(request, ticket_number):
|
|
ticket = get_object_or_404(Ticket, ticket_number=ticket_number)
|
|
ticket_updates = TicketUpdate.objects.filter(ticket=ticket).order_by('id')
|
|
for update in TicketUpdate.objects.filter(ticket=ticket).exclude(added_by=request.user).order_by('id'):
|
|
if not TicketRead.objects.filter(ticket_update=update, user=request.user).exists():
|
|
TicketRead.objects.create(ticket_update=update, user=request.user, read=True)
|
|
|
|
last_ticket_status = TicketStatus.objects.filter(ticket=ticket).last()
|
|
|
|
context = {
|
|
'ticket' : ticket,
|
|
'ticket_updates': ticket_updates,
|
|
'last_ticket_status': last_ticket_status
|
|
|
|
}
|
|
|
|
return render(request, 'details_templates/ticket-details.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def businessdetails(request, business_id):
|
|
business = get_object_or_404(Business, business_id=business_id)
|
|
context = {
|
|
'business' : business,
|
|
|
|
}
|
|
return render(request, 'details_templates/business-details.html', context)
|
|
|
|
@staff_login_required
|
|
def staffdetails( request, staff_id):
|
|
staff = get_object_or_404(StaffProfile, staff_id=staff_id)
|
|
|
|
context = {
|
|
'staff' : staff,
|
|
}
|
|
return render(request, 'details_templates/staff-details.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def taskdetails(request, task_id):
|
|
task = get_object_or_404(Task, task_id=task_id)
|
|
points = Point.objects.filter(task=task).order_by('-id')
|
|
|
|
context = {
|
|
'task': task,
|
|
'points' : points,
|
|
|
|
}
|
|
|
|
return render(request, 'details_templates/task-details.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def show_points_modal(request, task_id):
|
|
task = get_object_or_404(Task, task_id=task_id)
|
|
points = Point.objects.filter(task=task).order_by('-id')
|
|
context = {
|
|
'task' : task,
|
|
'points' : points,
|
|
|
|
}
|
|
return render(request, 'details_templates/showpoints-modal.html', context)
|
|
|
|
|
|
@staff_login_required
|
|
def timeline_modal(request, task_id):
|
|
task = Task.objects.get(task_id=task_id)
|
|
point_activities = PointActivity.objects.filter(point__task=task)
|
|
|
|
# Dictionary to store total time worked on each day
|
|
daily_totals = {}
|
|
|
|
for activity in point_activities:
|
|
date = activity.start_time.date()
|
|
hours, minutes, seconds = activity.total_time_in_hours_minutes_seconds()
|
|
total_time = timedelta(hours=hours, minutes=minutes, seconds=seconds)
|
|
|
|
# Add the total time to the corresponding day's total
|
|
if date in daily_totals:
|
|
daily_totals[date] += total_time
|
|
else:
|
|
daily_totals[date] = total_time
|
|
|
|
sorted_daily_totals = sorted(daily_totals.items())
|
|
formatted_totals = []
|
|
for date, total_time in sorted_daily_totals:
|
|
total_hours = total_time.days * 24 + total_time.seconds // 3600
|
|
total_minutes = (total_time.seconds % 3600) // 60
|
|
total_seconds = total_time.seconds % 60
|
|
formatted_totals.append((date, total_hours, total_minutes, total_seconds))
|
|
context = {
|
|
'task': task,
|
|
'sorted_daily_totals': sorted_daily_totals,
|
|
'formatted_totals':formatted_totals,
|
|
}
|
|
return render(request, 'details_templates/timeline-modal.html', context)
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def projectdetails(request, project_id):
|
|
project = get_object_or_404(Project, project_id=project_id)
|
|
is_pinned = project.is_pinned(request.user)
|
|
epics = Epic.objects.filter(project=project).order_by('-id')
|
|
|
|
project_notes = Note.objects.filter(project=project).order_by('-id')
|
|
statuses = ProjectStatus.objects.filter(project=project).order_by('-id')
|
|
|
|
all_tickets = Ticket.objects.filter(project=project)
|
|
all_tickets_with_update_date = all_tickets.annotate(
|
|
latest_update_date=Max('ticketupdate__date_added'))
|
|
all_tickets_ordered = all_tickets_with_update_date.order_by('-latest_update_date')
|
|
|
|
|
|
members = list(project.members.all())
|
|
|
|
if project.manager and project.manager in members:
|
|
members.remove(project.manager)
|
|
members.insert(0, project.manager)
|
|
|
|
for member in members:
|
|
tasks = project.task_set.filter(assigned_to=member)
|
|
total_time_seconds = 0
|
|
for task in tasks:
|
|
total_time_hours, total_time_minutes, total_time_seconds_task = task.total_task_time()
|
|
total_time_seconds += (total_time_hours * 3600) + (total_time_minutes * 60) + total_time_seconds_task
|
|
|
|
total_time_hours = total_time_seconds // 3600
|
|
total_time_minutes = (total_time_seconds % 3600) // 60
|
|
total_time_seconds = total_time_seconds % 60
|
|
|
|
member.total_time_worked_hours = total_time_hours
|
|
member.total_time_worked_minutes = total_time_minutes
|
|
member.total_time_worked_seconds = total_time_seconds
|
|
|
|
context = {
|
|
'project': project,
|
|
'epics': epics,
|
|
'project_notes' : project_notes,
|
|
'members': members,
|
|
'statuses' : statuses,
|
|
'all_tickets_ordered': all_tickets_ordered,
|
|
'is_pinned': is_pinned,
|
|
}
|
|
|
|
return render(request, 'details_templates/project-details.html', context)
|
|
|
|
|
|
|
|
|
|
@staff_login_required
|
|
def reaction_details_modal(request):
|
|
|
|
context = {
|
|
|
|
}
|
|
|
|
return render(request, 'details_templates/reaction-details-modal.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#FETCH EPIC RELATED TASKS
|
|
@staff_login_required
|
|
def get_tasks(request, epic_id):
|
|
epic = get_object_or_404(Epic, id=epic_id)
|
|
related_tasks = Task.objects.filter(epic=epic).order_by('-id')
|
|
|
|
context = {
|
|
'epic': epic,
|
|
'related_tasks': related_tasks,
|
|
}
|
|
|
|
return render(request, 'epic-fetched-tasks.html', context)
|
|
|
|
|
|
# TO DISPALY ALL THE OPEN TASKS OF THIS PROJECT
|
|
@staff_login_required
|
|
def open_tasks_for_project(request, project_id):
|
|
project = Project.objects.get(pk=project_id)
|
|
open_tasks = Task.objects.filter(
|
|
Q(project=project, status='Open') | Q(project=project, status='Working On')
|
|
).order_by('-id')
|
|
|
|
context = {
|
|
'project': project,
|
|
'open_tasks': open_tasks,
|
|
}
|
|
|
|
return render(request, 'project-open-tasks.html', context)
|
|
|
|
|
|
|
|
# TO FETCH THE EPICS OF THE SELECTED PROJECT WHEN EDITING A TASK
|
|
@staff_login_required
|
|
def fetch_epics(request):
|
|
project_id = request.GET.get('project_id')
|
|
epics = Epic.objects.filter(project_id=project_id).values('id', 'title')
|
|
return JsonResponse({'epics': list(epics)})
|
|
|
|
|
|
|
|
# TO UPDATE THE STATUS CONTAINER
|
|
@staff_login_required
|
|
def get_updated_last_status(request):
|
|
if request.user.is_authenticated:
|
|
last_status = Status.objects.filter(staff=request.user.staffprofile).last()
|
|
if last_status:
|
|
status_time = datetime.strptime(last_status.time, '%I:%M %p')
|
|
current_time = datetime.now().time()
|
|
time_difference = abs(datetime.combine(datetime.today(), current_time) - datetime.combine(datetime.today(), status_time.time()))
|
|
minutes_ago = int(time_difference.total_seconds() / 60)
|
|
else:
|
|
minutes_ago = 0
|
|
else:
|
|
last_status = None
|
|
minutes_ago = 0
|
|
|
|
if minutes_ago > 60:
|
|
hours_ago = minutes_ago // 60
|
|
remaining_minutes = minutes_ago % 60
|
|
hours_minutes_ago = f"{hours_ago}hr {remaining_minutes}min ago"
|
|
else:
|
|
hours_minutes_ago = f"{minutes_ago}min ago"
|
|
|
|
response_data = {
|
|
'last_status': last_status,
|
|
'minutes_ago': minutes_ago,
|
|
'hours_minutes_ago': hours_minutes_ago,
|
|
}
|
|
|
|
recent_status = render_to_string('recent-status.html', response_data)
|
|
|
|
return HttpResponse(recent_status)
|
|
|
|
|
|
# TO GET USER ACTIVITIES
|
|
@staff_login_required
|
|
def get_latest_activities(request):
|
|
latest_connections = Connection.objects.filter(
|
|
user__staffprofile__isnull=False
|
|
).values('user').annotate(
|
|
latest_connection=Max('date')
|
|
)
|
|
online_staff_profiles = []
|
|
for connection in latest_connections:
|
|
user_id = connection['user']
|
|
latest_connection = connection['latest_connection']
|
|
last_connection = Connection.objects.filter(user_id=user_id, date=latest_connection).first()
|
|
if last_connection.status == 'Online':
|
|
online_staff_profiles.append(last_connection.user.staffprofile)
|
|
if request.user.is_authenticated and request.user.is_superuser:
|
|
open_task_count = Task.objects.filter(status='Open').count()
|
|
working_on_task_count = Task.objects.filter(status='Working On').count()
|
|
elif request.user.is_authenticated:
|
|
open_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Open').count()
|
|
working_on_task_count = Task.objects.filter(assigned_to=request.user.staffprofile, status='Working On').count()
|
|
else:
|
|
open_task_count = 0
|
|
working_on_task_count = 0
|
|
|
|
total_tasks = open_task_count + working_on_task_count
|
|
|
|
|
|
today = datetime.now().date()
|
|
|
|
|
|
# Fetch the latest statuses from the last 24 hours
|
|
latest_statuses = Status.objects.filter(date=today).order_by('-id')
|
|
|
|
# Calculate time ago for each status and store it in a dictionary
|
|
latest_statuses_time_ago = [{'status': status, 'time_ago': calculate_time_ago(status)} for status in latest_statuses]
|
|
|
|
response_data = {
|
|
'total_tasks': total_tasks,
|
|
'latest_statuses_time_ago': latest_statuses_time_ago,
|
|
'online_staff_profiles' : online_staff_profiles,
|
|
}
|
|
|
|
recent_activities = render_to_string('recent-activities.html', response_data)
|
|
|
|
return HttpResponse(recent_activities)
|
|
|
|
|
|
@staff_login_required
|
|
def recent_activities_page(request):
|
|
|
|
context = {
|
|
|
|
}
|
|
|
|
return render(request, 'recent-activities-page.html', context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#Forgot Password Views
|
|
from django.contrib.auth.tokens import PasswordResetTokenGenerator
|
|
def forgot_password(request):
|
|
if request.method == 'POST':
|
|
email = request.POST.get('email')
|
|
user = User.objects.filter(email=email).first()
|
|
if user:
|
|
token = PasswordResetTokenGenerator().make_token(user)
|
|
current_site = get_current_site(request)
|
|
|
|
uid = urlsafe_base64_encode(force_bytes(user.pk))
|
|
reset_link = f"https://{current_site.domain}/reset-password/{uid}/{token}/"
|
|
|
|
mail_subject = 'Reset your password'
|
|
message = render_to_string('email_templates/forgot_password_email.html', {
|
|
'user': user,
|
|
'reset_link': reset_link,
|
|
})
|
|
print(reset_link)
|
|
send_mail(mail_subject, message, settings.EMAIL_HOST_USER, [user.email], html_message=message)
|
|
return render(request, 'forgot-password-sent.html')
|
|
else:
|
|
messages.error(request, 'No account is associated with this email.')
|
|
return render(request, 'forgot-password.html')
|
|
|
|
|
|
def reset_password(request, uidb64, token):
|
|
try:
|
|
uid = urlsafe_base64_decode(uidb64).decode()
|
|
user = User.objects.get(pk=uid)
|
|
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
|
|
user = None
|
|
|
|
if user and PasswordResetTokenGenerator().check_token(user, token):
|
|
if request.method == 'POST':
|
|
new_password = request.POST.get('new_password')
|
|
confirm_password = request.POST.get('confirm_password')
|
|
|
|
if new_password == confirm_password:
|
|
user.set_password(new_password)
|
|
user.save()
|
|
user = authenticate(request, username=user.username, password=new_password)
|
|
if user is not None:
|
|
login(request, user)
|
|
return redirect('home')
|
|
else:
|
|
return HttpResponse('Authentication failed!')
|
|
else:
|
|
return render(request, 'forgot-password-confirmation.html')
|
|
else:
|
|
return render(request, 'forgot-password-confirmation.html')
|
|
else:
|
|
return HttpResponse('Activation link is invalid!')
|
|
|
|
|
|
|
|
def fetch_projects_by_status(request, status=None):
|
|
user = request.user
|
|
|
|
if user.is_superuser:
|
|
projects = Project.objects.all().order_by('-project_id')
|
|
else:
|
|
projects = Project.objects.filter( Q(manager=user.staffprofile) | Q(members=user.staffprofile)).distinct().order_by('-project_id')
|
|
|
|
|
|
if status:
|
|
filtered_projects = []
|
|
for project in projects:
|
|
last_status = ProjectStatus.objects.filter(project = project).last()
|
|
if last_status.status == status:
|
|
filtered_projects.append(project)
|
|
else:
|
|
filtered_projects = projects
|
|
|
|
|
|
latest_pinned = PinnedProject.objects.filter(user=request.user)[:4]
|
|
latest_pinned_project_ids = [pinned.project.id for pinned in latest_pinned]
|
|
latest_pinned_projects = [pinned.project for pinned in latest_pinned]
|
|
for project in latest_pinned_projects:
|
|
total_time = project.total_time_worked(request.user)
|
|
project.total_time_worked_hours = total_time['hours']
|
|
project.total_time_worked_minutes = total_time['minutes']
|
|
project.total_time_worked_seconds = total_time['seconds']
|
|
|
|
project.open_user_tasks_count = project.open_tasks_count(request.user)
|
|
|
|
|
|
|
|
filtered_projects = [project for project in filtered_projects if project.id not in latest_pinned_project_ids] #Exclude pinned projects
|
|
for project in filtered_projects:
|
|
total_time = project.total_time_worked(request.user)
|
|
project.total_time_worked_hours = total_time['hours']
|
|
project.total_time_worked_minutes = total_time['minutes']
|
|
project.total_time_worked_seconds = total_time['seconds']
|
|
|
|
project.open_user_tasks_count = project.open_tasks_count(request.user)
|
|
|
|
context = {
|
|
'filtered_projects': filtered_projects,
|
|
'latest_pinned_projects': latest_pinned_projects,
|
|
'status': status,
|
|
}
|
|
return render(request, 'projects-by-status.html', context)
|