Skip to content
Open
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
3 changes: 3 additions & 0 deletions django_app/coworking/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Coworking – Django port

Uruchom zgodnie z instrukcjami w wiadomości.
1 change: 1 addition & 0 deletions django_app/coworking/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

105 changes: 105 additions & 0 deletions django_app/coworking/api/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.db.models import Count, Q
from django.utils.html import format_html
from django.urls import path
from django.shortcuts import render
from django.http import JsonResponse
from .models import User, Reservation
from datetime import datetime, timedelta

@admin.register(User)
class UserAdmin(BaseUserAdmin):
model = User
list_display = ('email', 'full_name', 'is_active', 'is_staff', 'is_superuser', 'reservation_count', 'created_at', 'last_login')
ordering = ('email',)
search_fields = ('email', 'full_name')
list_filter = ('is_active', 'is_staff', 'is_superuser', 'created_at')
fieldsets = ((None, {'fields': ('email', 'password')}), ('Personal info', {'fields': ('full_name',)}), ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}), ('Important dates', {'fields': ('last_login', 'created_at')}))
add_fieldsets = ((None, {'classes': ('wide',), 'fields': ('email', 'password1', 'password2', 'is_staff', 'is_superuser')}),)
filter_horizontal = ('groups', 'user_permissions')
actions = ['make_staff', 'deactivate_users', 'activate_users']

def reservation_count(self, obj):
count = Reservation.objects.filter(email=obj.email).count()
return format_html('<span style="color: {};">{}</span>', 'green' if count > 0 else 'gray', count)
reservation_count.short_description = 'Reservations'

def make_staff(self, request, queryset):
updated = queryset.update(is_staff=True)
self.message_user(request, f'{updated} users promoted to staff.')
make_staff.short_description = "Make selected users staff"

def deactivate_users(self, request, queryset):
updated = queryset.update(is_active=False)
self.message_user(request, f'{updated} users deactivated.')
deactivate_users.short_description = "Deactivate selected users"

def activate_users(self, request, queryset):
updated = queryset.update(is_active=True)
self.message_user(request, f'{updated} users activated.')
activate_users.short_description = "Activate selected users"

def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('analytics/', self.admin_site.admin_view(self.user_analytics), name='user_analytics'),
]
return custom_urls + urls

def user_analytics(self, request):
# Analytics data
total_users = User.objects.count()
active_users = User.objects.filter(is_active=True).count()
staff_users = User.objects.filter(is_staff=True).count()

# Recent activity
last_7_days = datetime.now() - timedelta(days=7)
new_users = User.objects.filter(created_at__gte=last_7_days).count()

# Most active users
active_users_data = Reservation.objects.values('email')\
.annotate(count=Count('email'))\
.order_by('-count')[:10]

context = {
'title': 'User Analytics',
'total_users': total_users,
'active_users': active_users,
'staff_users': staff_users,
'new_users': new_users,
'active_users_data': active_users_data,
}

return render(request, 'admin/user_analytics.html', context)

@admin.register(Reservation)
class ReservationAdmin(admin.ModelAdmin):
list_display = ('id', 'seat_id', 'date', 'name', 'email', 'created_at', 'status_badge')
list_filter = ('date', 'created_at', 'seat_id')
search_fields = ('id', 'seat_id', 'name', 'email')
ordering = ('-created_at',)
actions = ['cancel_reservations', 'export_reservations']

def status_badge(self, obj):
today = datetime.now().strftime('%Y-%m-%d')
if obj.date < today:
return format_html('<span style="color: gray; font-weight: bold;">PAST</span>')
elif obj.date == today:
return format_html('<span style="color: orange; font-weight: bold;">TODAY</span>')
else:
return format_html('<span style="color: green; font-weight: bold;">FUTURE</span>')
status_badge.short_description = 'Status'

def cancel_reservations(self, request, queryset):
count = queryset.count()
queryset.delete()
self.message_user(request, f'{count} reservations cancelled.')
cancel_reservations.short_description = "Cancel selected reservations"

def export_reservations(self, request, queryset):
# This would typically redirect to a view that generates CSV
self.message_user(request, f'Export functionality for {queryset.count()} reservations.')
export_reservations.short_description = "Export selected reservations"
list_filter = ('date',)
search_fields = ('id', 'seat_id', 'name', 'email')
235 changes: 235 additions & 0 deletions django_app/coworking/api/admin_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
from rest_framework import status, permissions
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from django.contrib.auth import get_user_model
from django.db.models import Count, Q
from django.http import HttpResponse
from .models import Reservation
from .permissions import IsSuperUser
from datetime import datetime, timedelta
import csv
import json

User = get_user_model()

@api_view(['GET'])
@permission_classes([IsSuperUser])
def admin_dashboard_stats(request):
"""Get comprehensive dashboard statistics for superuser"""

# Basic counts
total_users = User.objects.count()
active_users = User.objects.filter(is_active=True).count()
staff_users = User.objects.filter(is_staff=True).count()
total_reservations = Reservation.objects.count()

# Recent activity (last 30 days)
last_30_days = datetime.now() - timedelta(days=30)
new_users = User.objects.filter(created_at__gte=last_30_days).count()
recent_reservations = Reservation.objects.filter(created_at__gte=last_30_days).count()

# Today's activity
today = datetime.now().strftime('%Y-%m-%d')
today_reservations = Reservation.objects.filter(date=today).count()

# Most popular seats
popular_seats = Reservation.objects.values('seat_id')\
.annotate(count=Count('seat_id'))\
.order_by('-count')[:5]

# Most active users
active_users_data = Reservation.objects.values('email')\
.annotate(count=Count('email'))\
.order_by('-count')[:5]

# Recent reservations
recent_reservations_list = Reservation.objects.order_by('-created_at')[:10]

return Response({
'overview': {
'total_users': total_users,
'active_users': active_users,
'staff_users': staff_users,
'total_reservations': total_reservations,
'new_users_30d': new_users,
'recent_reservations_30d': recent_reservations,
'today_reservations': today_reservations,
},
'popular_seats': list(popular_seats),
'active_users': list(active_users_data),
'recent_reservations': [
{
'id': res.id,
'seat_id': res.seat_id,
'date': res.date,
'name': res.name,
'email': res.email,
'created_at': res.created_at
} for res in recent_reservations_list
]
})

@api_view(['POST'])
@permission_classes([IsSuperUser])
def bulk_user_operations(request):
"""Perform bulk operations on users"""
action = request.data.get('action')
user_ids = request.data.get('user_ids', [])

if not action or not user_ids:
return Response({'error': 'Action and user_ids required'}, status=400)

users = User.objects.filter(id__in=user_ids)

if action == 'activate':
count = users.update(is_active=True)
return Response({'message': f'{count} users activated'})

elif action == 'deactivate':
count = users.update(is_active=False)
return Response({'message': f'{count} users deactivated'})

elif action == 'make_staff':
count = users.update(is_staff=True)
return Response({'message': f'{count} users promoted to staff'})

elif action == 'remove_staff':
# Don't allow removing staff from superusers
count = users.exclude(is_superuser=True).update(is_staff=False)
return Response({'message': f'{count} users removed from staff'})

else:
return Response({'error': 'Invalid action'}, status=400)

@api_view(['POST'])
@permission_classes([IsSuperUser])
def bulk_reservation_operations(request):
"""Perform bulk operations on reservations"""
action = request.data.get('action')
reservation_ids = request.data.get('reservation_ids', [])

if not action or not reservation_ids:
return Response({'error': 'Action and reservation_ids required'}, status=400)

reservations = Reservation.objects.filter(id__in=reservation_ids)

if action == 'cancel':
count = reservations.count()
reservations.delete()
return Response({'message': f'{count} reservations cancelled'})

elif action == 'export':
# Return reservation data for export
data = [
{
'id': res.id,
'seat_id': res.seat_id,
'date': res.date,
'name': res.name,
'email': res.email,
'notes': res.notes,
'created_at': res.created_at.isoformat()
} for res in reservations
]
return Response({'data': data, 'count': len(data)})

else:
return Response({'error': 'Invalid action'}, status=400)

@api_view(['GET'])
@permission_classes([IsSuperUser])
def export_reservations_csv(request):
"""Export reservations to CSV"""
# Get date range from query parameters
date_from = request.GET.get('date_from')
date_to = request.GET.get('date_to')

queryset = Reservation.objects.all()

if date_from:
queryset = queryset.filter(date__gte=date_from)
if date_to:
queryset = queryset.filter(date__lte=date_to)

queryset = queryset.order_by('date', 'seat_id')

# Create CSV response
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="reservations_{datetime.now().strftime("%Y%m%d")}.csv"'

writer = csv.writer(response)
writer.writerow(['ID', 'Seat ID', 'Date', 'Name', 'Email', 'Notes', 'Created At'])

for reservation in queryset:
writer.writerow([
reservation.id,
reservation.seat_id,
reservation.date,
reservation.name,
reservation.email,
reservation.notes,
reservation.created_at
])

return response

@api_view(['GET'])
@permission_classes([IsSuperUser])
def export_users_csv(request):
"""Export users to CSV"""
queryset = User.objects.all().order_by('email')

# Create CSV response
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = f'attachment; filename="users_{datetime.now().strftime("%Y%m%d")}.csv"'

writer = csv.writer(response)
writer.writerow(['Email', 'Full Name', 'Is Active', 'Is Staff', 'Is Superuser', 'Created At', 'Last Login'])

for user in queryset:
writer.writerow([
user.email,
user.full_name,
user.is_active,
user.is_staff,
user.is_superuser,
user.created_at,
user.last_login
])

return response

@api_view(['GET'])
@permission_classes([IsSuperUser])
def system_health_check(request):
"""Check system health and performance"""

# Database connectivity
try:
User.objects.count()
db_status = 'OK'
except Exception as e:
db_status = f'ERROR: {str(e)}'

# Recent errors (if logging is set up)
# This is a placeholder - in real implementation you'd check logs

# Disk space (simplified check)
import os
try:
statvfs = os.statvfs('.')
free_space_gb = (statvfs.f_frsize * statvfs.f_bavail) / (1024**3)
disk_status = f'{free_space_gb:.2f} GB free'
except:
disk_status = 'Unknown'

# Active sessions (approximation)
active_sessions = User.objects.filter(last_login__gte=datetime.now() - timedelta(hours=24)).count()

return Response({
'database': db_status,
'disk_space': disk_status,
'active_users_24h': active_sessions,
'timestamp': datetime.now().isoformat(),
'status': 'healthy' if db_status == 'OK' else 'warning'
})
Loading