123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- import datetime
- import json
- from django.db import IntegrityError
- from django.http import HttpResponseForbidden, HttpResponseNotFound, HttpResponseRedirect, JsonResponse, HttpResponseNotAllowed
- from django.shortcuts import render
- from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
- from django.views.decorators.csrf import csrf_exempt
- from django.views.decorators.vary import vary_on_cookie
- from django.views.decorators.cache import cache_page
- from django.utils.translation import gettext as _
- from django.contrib.auth.models import User
- from .forms import CreateEventForm, LoginForm, UpdateSlotsForm
- from .models import Event, Participant, Date
- from .helpers import slots2string, string2slots, get_slot_count, slots2grid
- @cache_page(60 * 15)
- def index(request):
- return render(request, 'zitap/index.html')
- def my_events(request):
- if not request.session.get('user_id'):
- form = LoginForm({'username': request.session.get('username', '')})
- form.add_error('password', _('Please enter a password.'))
- return render(request, 'zitap/login.html', {'form': form, 'url': 'my-events', 'text': _('Login to My Events')})
- print(request.session.get('user_id'))
- events = Event.objects.filter(participant__user=request.user).prefetch_related('date_set', 'participant_set', 'participant_set__user')
- return render(request, 'zitap/my-events.html', {
- 'events': events,
- })
- def about(request):
- return render(request, 'zitap/about.html')
- @cache_page(60 * 15)
- def create_event(request):
- if request.method == 'POST':
- form = CreateEventForm(request.POST)
- if form.is_valid():
- data = form.cleaned_data
- # Try to create the event. If the url is already taken, try again.
- n = 0
- while n<10:
- try:
- event = Event.objects.create(
- name=data['event_name'],
- start_time=datetime.time(int(data['start_time']), 0),
- end_time=datetime.time(int(data['end_time']), 0),
- slot_interval=datetime.timedelta(minutes=int(data['slot_interval'])),
- )
- for date in data['event_date']:
- event.date_set.create(date=date)
- event.save()
- return HttpResponseRedirect(f'/{event.url}')
- except IntegrityError:
- n += 1
- form.add_error(None, _('Could not create event. Please try again.'))
- else:
- form = CreateEventForm()
- return render(request, 'zitap/create-event.html', {'form': form})
- @cache_page(60 * 15)
- @vary_on_cookie
- def event(request, url):
- event = Event.objects.filter(url=url).prefetch_related('date_set', 'participant_set', 'participant_set__user').first()
- participants = list(event.participant_set.all()) if event else []
- if not event:
- return render(request, 'zitap/event-not-found.html')
-
- # Check if the user is logged in
- participant = None
- if 'username' in request.session:
- for participant in participants:
- if participant.name == request.session['username']:
- break
- else:
- participant = None
- login_form = None
- n_slots = get_slot_count(event)
- update_form = UpdateSlotsForm(initial={'slots': slots2string(participant, n_slots)}, event=event, n_slots=n_slots, participant=participant)
- else:
- login_form = LoginForm()
- update_form = None
- return render(
- request,
- 'zitap/event.html',
- {'event': event, 'grid': slots2grid(event, participants, False), 'login_form': login_form, 'update_form': update_form}
- )
- def login(request, url):
- if url == 'my-events':
- text = _('Login to My Events')
- elif Event.objects.filter(url=url).exists():
- text = _('Login to Update Slots')
- else:
- return render(request, 'zitap/event-not-found.html')
- if request.method == 'POST':
- form = LoginForm(request.POST)
- elif 'username' in request.session:
- return HttpResponseRedirect(f'/{url}')
- else:
- form = LoginForm()
- if form.is_valid():
- data = form.cleaned_data
- user = authenticate(request, username=data['username'], password=data.get('password'))
- if user is None and data.get('password'):
- try:
- user = User.objects.create_user(data['username'], password=data.get('password'))
- except IntegrityError:
- form.add_error('password', _('Wrong password'))
- return render(request, 'zitap/login.html', {'form': form, 'url': url, 'text': text})
- elif user is None and User.objects.filter(username=data['username']).exists():
- form.add_error('username', _('Username already exists'))
- return render(request, 'zitap/login.html', {'form': form, 'url': url, 'text': text})
- if user:
- auth_login(request, user)
- request.session['user_id'] = user.id
- elif 'user_id' in request.session:
- del request.session['user_id']
- request.session['username'] = data['username']
- return HttpResponseRedirect(f'/{url}')
- return render(request, 'zitap/login.html', {'form': form, 'url': url, 'text': text})
- def logout(request, url):
- auth_logout(request)
- if url == 'my-events':
- return HttpResponseRedirect(f'/my-events/login')
- elif Event.objects.filter(url=url).exists():
- return HttpResponseRedirect(f'/{url}')
- else:
- return render(request, 'zitap/event-not-found.html')
- def update_slots(request, url):
- try:
- event = Event.objects.get(url=url)
- except Event.DoesNotExist:
- return render(request, 'zitap/event-not-found.html')
- if request.method != 'POST':
- return HttpResponseNotAllowed(['POST'])
-
- if 'username' not in request.session:
- return HttpResponseForbidden()
- slot_count = get_slot_count(event)
- participant = event.participant_set.filter(name=request.session['username'], event=event).first()
- form = UpdateSlotsForm(request.POST, event=event, n_slots=slot_count, participant=participant)
- if form.is_valid():
- data = form.cleaned_data
- if data['slots'] == '0' * slot_count and participant:
- participant.delete()
- elif not participant:
- participant = Participant.objects.create(name=request.session['username'], user_id=request.session['user_id'], event=event, slots=string2slots(data['slots'], slot_count))
- else:
- participant.slots = string2slots(data['slots'], slot_count)
- participant.save()
- return HttpResponseRedirect(f'/{event.url}')
- def event_api(request, url):
- """
- REST JSON API for an event
- """
- try:
- event = Event.objects.get(url=url)
- except Event.DoesNotExist:
- return JsonResponse({'error': 'Event not found'}, status=404)
- if request.method == 'GET':
- return JsonResponse({
- 'name': event.name,
- 'url': event.url,
- 'start_time': event.start_time.strftime('%H:%M'),
- 'end_time': event.end_time.strftime('%H:%M'),
- 'slot_interval': event.slot_interval.seconds // 60,
- 'dates': [date.date.strftime('%Y-%m-%d') for date in event.date_set.all()],
- })
- else:
- return HttpResponseNotAllowed(['GET'])
- @csrf_exempt
- def slots_api(request, url):
- """
- REST JSON API for slots of all participants of an event
- Slots are represented as a string of 0s and 1s where 0 means the slot is available and 1 means the slot is taken.
- The string begins with the first slot of the first day of the event and ends with the last slot of the last day of the event.
- """
- event = Event.objects.filter(url=url).prefetch_related('date_set', 'participant_set', 'participant_set__user').first()
- participants = list(event.participant_set.all()) if event else []
- if not event:
- return HttpResponseNotFound()
- slot_count = get_slot_count(event)
- # Check if the user is logged in and wants to update their slots
- if 'username' in request.session and request.method == 'POST':
- for participant in participants:
- if participant.name == request.session['username']:
- break
- else:
- participant = None
-
- slot_count = get_slot_count(event)
- form = UpdateSlotsForm(request.POST, event=event, n_slots=slot_count, participant=participant)
- if form.is_valid():
- data = form.cleaned_data
- if data['slots'] == '0' * slot_count and participant:
- participant.delete()
- elif not participant:
- participant = Participant.objects.create(name=request.session['username'], user_id=request.session.get('user_id'), event=event, slots=string2slots(data['slots'], slot_count))
- else:
- participant.slots = string2slots(data['slots'], slot_count)
- participant.save()
- # Get the slots of each participant
- data = {
- 'username': request.session.get('username'),
- 'n_slots': slot_count,
- 'participants': [participant.name for participant in participants],
- 'slots': [slots2string(participant, slot_count) for participant in participants],
- }
-
- return JsonResponse(data)
-
|