Internal
Public Access
Features: - Django-based REST API with web interface - Task management with tags, priorities, and due dates - Time tracking with start/stop timers - Subtasks support - Task filtering (all, today, upcoming, overdue, completed) - Tag-based organization with color coding - Sorting by due date and priority - Auto-assign tags when filtering - Responsive 3-pane layout (sidebar, task list, detail panel) - Task sharing between users - Mobile-responsive design with dark mode support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
97 lines
2.6 KiB
Python
97 lines
2.6 KiB
Python
"""
|
|
Notification views for KeepItGoing.
|
|
"""
|
|
|
|
from django.utils import timezone
|
|
from rest_framework import generics, permissions, status
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.response import Response
|
|
|
|
from .models import Notification
|
|
from .serializers import NotificationSerializer
|
|
|
|
|
|
class NotificationListAPIView(generics.ListAPIView):
|
|
"""API endpoint for listing notifications."""
|
|
|
|
serializer_class = NotificationSerializer
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get_queryset(self):
|
|
queryset = Notification.objects.filter(user=self.request.user)
|
|
|
|
# Filter by read status
|
|
is_read = self.request.query_params.get('is_read')
|
|
if is_read is not None:
|
|
queryset = queryset.filter(is_read=is_read.lower() == 'true')
|
|
|
|
return queryset
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def mark_read(request, notification_id):
|
|
"""Mark a notification as read."""
|
|
try:
|
|
notification = Notification.objects.get(
|
|
id=notification_id,
|
|
user=request.user
|
|
)
|
|
except Notification.DoesNotExist:
|
|
return Response(
|
|
{'error': 'Notification not found'},
|
|
status=status.HTTP_404_NOT_FOUND
|
|
)
|
|
|
|
notification.is_read = True
|
|
notification.read_at = timezone.now()
|
|
notification.save()
|
|
|
|
return Response(NotificationSerializer(notification).data)
|
|
|
|
|
|
@api_view(['POST'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def mark_all_read(request):
|
|
"""Mark all notifications as read."""
|
|
Notification.objects.filter(
|
|
user=request.user,
|
|
is_read=False
|
|
).update(
|
|
is_read=True,
|
|
read_at=timezone.now()
|
|
)
|
|
|
|
return Response({'status': 'All notifications marked as read'})
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def unread_count(request):
|
|
"""Get count of unread notifications."""
|
|
count = Notification.objects.filter(
|
|
user=request.user,
|
|
is_read=False
|
|
).count()
|
|
|
|
return Response({'unread_count': count})
|
|
|
|
|
|
@api_view(['DELETE'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def delete_notification(request, notification_id):
|
|
"""Delete a notification."""
|
|
try:
|
|
notification = Notification.objects.get(
|
|
id=notification_id,
|
|
user=request.user
|
|
)
|
|
except Notification.DoesNotExist:
|
|
return Response(
|
|
{'error': 'Notification not found'},
|
|
status=status.HTTP_404_NOT_FOUND
|
|
)
|
|
|
|
notification.delete()
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|