Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions blt/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@
),
path("auth/delete", AuthApiViewset.as_view({"delete": "delete"}), name="auth-delete-api"),
path("api/v1/tags", TagApiViewset.as_view({"get": "list", "post": "create"}), name="tags-api"),
path("sizzle/", website.views.sizzle, name="sizzle"),
path("api/timelogsreport/", website.views.TimeLogListAPIView, name="timelogsreport"),
]

if settings.DEBUG:
Expand Down
2 changes: 2 additions & 0 deletions website/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
Suggestion,
SuggestionVotes,
Tag,
TimeLog,
Transaction,
UserProfile,
Wallet,
Expand Down Expand Up @@ -416,6 +417,7 @@ class TagAdmin(admin.ModelAdmin):
admin.site.register(Blocked, BlockedAdmin)
admin.site.register(Suggestion, SuggestionAdmin)
admin.site.register(SuggestionVotes, SuggestionVotesAdmin)
admin.site.register(TimeLog)

# Register missing models
admin.site.register(InviteFriend)
Expand Down
7 changes: 7 additions & 0 deletions website/templates/includes/sidenav.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@
<span>Sponsor</span>
</a>
</li>
<li class="{% if request.path == '/sizzle/' %}bg-gray-200{% endif %}">
<a href="{% url 'sizzle' %}"
class="flex items-center w-full text-black no-underline p-2">
<div class="w-8 mr-4">⏱️</div>
<span>Sizzle</span>
</a>
</li>
<li class="{% if request.path == '/scoreboard/' %}bg-gray-200{% endif %}">
<a href="{% url 'scoreboard' %}"
class="flex items-center w-full text-black no-underline p-2">
Expand Down
131 changes: 131 additions & 0 deletions website/templates/sizzle/sizzle.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<link rel="stylesheet"
type="text/css"
href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />
<div class="container mx-auto p-6">
<!-- Include the left navigation -->
{% include "includes/sidenav.html" %}
<!-- Main Content Section -->
<div class="main-content w-full">
<div class="flex justify-between items-center mb-8 mt-8">
<h1 class="text-4xl font-semibold text-gray-800 mb-8">Your Sizzle Report</h1>
<div class="flex space-x-2">
<input type="text"
name="daterange"
id="daterange"
class="bg-red-500 text-white py-2 px-6 rounded-md shadow-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-300 cursor-pointer"
readonly />
</div>
</div>
<!-- Report Table -->
<div id="report-table">
<div class="bg-white shadow-lg rounded-lg overflow-hidden"
id="report-item">
<div class="bg-red-500 text-white text-center py-4 text-lg font-semibold">
<!-- if the sizzle data have the show here value of sizzle data "date" key value else today date -->
{% if sizzle_data %}
{{ sizzle_data.date }}
{% else %}
No Data
{% endif %}
</div>
<table class="min-w-full bg-white">
<thead>
<tr class="bg-red-500 text-white text-sm uppercase tracking-wider">
<th class="text-left py-3 px-4 border-b border-gray-200">Issue Title</th>
<th class="text-left py-3 px-4 border-b border-gray-200">Started</th>
<th class="text-left py-3 px-4 border-b border-gray-200">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-3 px-4 border-b border-gray-200">
{% if sizzle_data %}
{{ sizzle_data.issue_title }}
{% else %}
No Data
{% endif %}
</td>
<td class="py-3 px-4 border-b border-gray-200">
{% if sizzle_data %}
{{ sizzle_data.start_time }}
{% else %}
No Data
{% endif %}
</td>
<td class="py-3 px-4 border-b border-gray-200">
{% if sizzle_data %}
{{ sizzle_data.duration }}
{% else %}
No Data
{% endif %}
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script type="text/javascript"
src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript"
src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript"
src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<script type="text/javascript">
$(function() {
$('input[name="daterange"]').daterangepicker({
opens: 'left',
locale: {
format: 'YYYY-MM-DD'
}
}, function(start, end, label) {
$('#report-date').text(start.format('D.M.YYYY') + ' - ' + end.format('D.M.YYYY') + ' Report');

// Fetch and update report logs
$.ajax({
url: '{% url "timelogsreport" %}',
data: {
start_date: start.format('YYYY-MM-DDTHH:mm:ssZ'),
end_date: end.format('YYYY-MM-DDTHH:mm:ssZ')
},
success: function(data) {
// if success the report-table div will be fully clean and the new data will be added for each item in the data added like present item
$('#report-table').empty();
data.forEach(function(item) {
$('#report-table').append(`
<div class="bg-white shadow-lg rounded-lg overflow-hidden mb-8">
<div class="bg-red-500 text-white text-center py-4 text-lg font-semibold">
${item.date}
</div>
<table class="min-w-full bg-white">
<thead>
<tr class="bg-red-500 text-white text-sm uppercase tracking-wider">
<th class="text-left py-3 px-4 border-b border-gray-200">Issue Title</th>
<th class="text-left py-3 px-4 border-b border-gray-200">Started</th>
<th class="text-left py-3 px-4 border-b border-gray-200">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td class="py-3 px-4 border-b border-gray-200">${item.issue_title}</td>
<td class="py-3 px-4 border-b border-gray-200">${item.start_time}</td>
<td class="py-3 px-4 border-b border-gray-200">${item.duration}</td>
</tr>
</tbody>
</table>
</div>
`);
});
},
error: function(xhr, status, error) {
alert('An error occurred while fetching the report logs.');
}
});
});
});
</script>
{% endblock content %}
1 change: 1 addition & 0 deletions website/tests_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def check_urls(urlpatterns, prefix=""):
"/error/",
"/tz_detect/set/",
"/leaderboard/api/",
"/api/timelogsreport/",
]
if not any(x in url for x in matches):
response = self.client.get(url)
Expand Down
131 changes: 130 additions & 1 deletion website/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import urllib.parse
import urllib.request
import uuid
from collections import deque
from collections import defaultdict, deque
from datetime import datetime, timedelta, timezone
from decimal import Decimal
from pathlib import Path
Expand Down Expand Up @@ -63,6 +63,7 @@
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.dateparse import parse_datetime
from django.utils.decorators import method_decorator
from django.utils.timezone import now
from django.views.decorators.csrf import csrf_exempt
Expand Down Expand Up @@ -98,6 +99,7 @@
Subscription,
Suggestion,
SuggestionVotes,
TimeLog,
UserProfile,
Wallet,
Winner,
Expand Down Expand Up @@ -5003,3 +5005,130 @@ def add_suggestions(request):
def view_suggestions(request):
suggestion = Suggestion.objects.all()
return render(request, "feature_suggestion.html", {"suggestions": suggestion})


def sizzle(request):
# Check if the user is authenticated; if not, redirect to the home page with a message
print(request.user)
if not request.user.is_authenticated:
messages.error(request, "Please login to access the Sizzle page.")
return redirect("index")

# Initialize the variable to store Sizzle tracking data
sizzle_data = None

# Fetch the latest TimeLog entry for the current user
last_data = TimeLog.objects.filter(user=request.user).order_by("-created").first()

if last_data:
# Fetch all TimeLog entries created on the same date as the last_data entry
all_data = TimeLog.objects.filter(
user=request.user, created__date=last_data.created.date()
).order_by("created")

# Calculate the total duration for all the entries on the same date
total_duration = sum((entry.duration for entry in all_data if entry.duration), timedelta())

# Format total duration to minutes and seconds
total_duration_seconds = total_duration.total_seconds()
formatted_duration = (
f"{int(total_duration_seconds // 60)} min {int(total_duration_seconds % 60)} sec"
)

# Get the first entry's GitHub issue URL and extract the repository path and issue number
github_issue_url = all_data.first().github_issue_url

# Fetch the issue title from GitHub API
issue_title = get_github_issue_title(github_issue_url)

# Format start time and date to human-readable format
start_time = all_data.first().start_time.strftime("%I:%M %p")
date = last_data.created.strftime("%d %B %Y") # Example: '14 August 2024'

# Prepare sizzle_data with human-readable format
sizzle_data = {
"issue_title": issue_title,
"duration": formatted_duration,
"start_time": start_time,
"date": date,
}

return render(request, "sizzle/sizzle.html", {"sizzle_data": sizzle_data})


def TimeLogListAPIView(request):
print(request.user)
if not request.user.is_authenticated:
return JsonResponse({"error": "Unauthorized"}, status=status.HTTP_401_UNAUTHORIZED)

start_date_str = request.GET.get("start_date")
end_date_str = request.GET.get("end_date")

if not start_date_str or not end_date_str:
return JsonResponse(
{"error": "Both start_date and end_date are required."},
status=status.HTTP_400_BAD_REQUEST,
)

start_date = parse_datetime(start_date_str)
end_date = parse_datetime(end_date_str)

if not start_date or not end_date:
return JsonResponse({"error": "Invalid date format."}, status=status.HTTP_400_BAD_REQUEST)

# Fetch the time logs within the specified date range for the authenticated user
time_logs = TimeLog.objects.filter(
user=request.user, created__range=[start_date, end_date]
).order_by("created")

# Group time logs by date
grouped_logs = defaultdict(list)
for log in time_logs:
date_str = log.created.strftime("%Y-%m-%d")
grouped_logs[date_str].append(log)

# Prepare the final structured response
response_data = []
for date, logs in grouped_logs.items():
first_log = logs[0]
total_duration = sum((log.duration for log in logs if log.duration), timedelta())

# Format total duration to minutes and seconds
total_duration_seconds = total_duration.total_seconds()
formatted_duration = (
f"{int(total_duration_seconds // 60)} min {int(total_duration_seconds % 60)} sec"
)

# Fetch the issue title using GitHub API (for the first log of the day)
issue_title = get_github_issue_title(first_log.github_issue_url)

# Format start time and date to human-readable format
start_time = first_log.start_time.strftime("%I:%M %p")
formatted_date = first_log.created.strftime("%d %B %Y") # Example: '14 August 2024'

# Prepare the day's data
day_data = {
"issue_title": issue_title,
"duration": formatted_duration,
"start_time": start_time,
"date": formatted_date,
}

response_data.append(day_data)

return JsonResponse(response_data, safe=False, status=status.HTTP_200_OK)


def get_github_issue_title(github_issue_url):
"""Helper function to fetch the title of a GitHub issue."""
try:
repo_path = "/".join(github_issue_url.split("/")[3:5])
issue_number = github_issue_url.split("/")[-1]
github_api_url = f"https://api.github.com/repos/{repo_path}/issues/{issue_number}"
response = requests.get(github_api_url)
if response.status_code == 200:
issue_data = response.json()
return issue_data.get("title", "No Title")
return f"Issue #{issue_number}"
except Exception:
return "No Title"