Skip to content

Commit

Permalink
Merge pull request #291 from kenanwright1988/calendar_for_registrants
Browse files Browse the repository at this point in the history
Calendar for registrants
  • Loading branch information
kenanwright1988 authored Oct 9, 2024
2 parents 692c13a + 9ada358 commit 355429e
Show file tree
Hide file tree
Showing 17 changed files with 1,161 additions and 16 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ venv/
MYNOTES.md
staticfiles
data/
todo.txt
node_modules/
4 changes: 3 additions & 1 deletion hackathon/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
HackTeam,
HackProject,
HackProjectScore,
HackProjectScoreCategory)
HackProjectScoreCategory,
Event)


# Register your models here.
Expand All @@ -16,3 +17,4 @@
admin.site.register(HackProject)
admin.site.register(HackProjectScore)
admin.site.register(HackProjectScoreCategory)
admin.site.register(Event)
70 changes: 69 additions & 1 deletion hackathon/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from accounts.models import Organisation
from .models import Hackathon, HackProject, HackAward, HackTeam, \
HackProjectScoreCategory, HackAwardCategory
HackProjectScoreCategory, HackAwardCategory, Event
from .lists import STATUS_TYPES_CHOICES


Expand Down Expand Up @@ -194,3 +194,71 @@ def __init__(self, *args, **kwargs):
self.fields['winning_project'] = forms.ModelChoiceField(
queryset=hack_projects)
self.fields['winning_project'].required = False


class EventForm(forms.ModelForm):
"""
Form to create or update an Event
"""
title = forms.CharField(
label="Webinar Title",
widget=forms.TextInput(attrs={'class': 'form-control'})
)
start = forms.DateTimeField(
label="Start Time",
input_formats=['%d/%m/%Y %H:%M'],
widget=forms.DateTimeInput(
format='%d/%m/%Y %H:%M',
attrs={
'placeholder': 'DD/MM/YYYY HH:MM',
'autocomplete': 'off',
'class': 'form-control'
}
)
)
end = forms.DateTimeField(
label="End Time",
input_formats=['%d/%m/%Y %H:%M'],
widget=forms.DateTimeInput(
format='%d/%m/%Y %H:%M',
attrs={
'placeholder': 'DD/MM/YYYY HH:MM',
'autocomplete': 'off',
'class': 'form-control'
}
)
)
body = forms.CharField(
label="Description",
widget=forms.Textarea(attrs={'rows': 4, 'class': 'form-control'})
)
webinar_link = forms.URLField(
label="Webinar Link",
required=False,
widget=forms.URLInput(attrs={'class': 'form-control'})
)
webinar_code = forms.CharField(
label="Webinar Join Code",
required=False,
widget=forms.Textarea(attrs={'rows': 1, 'class': 'form-control'})
)
class Meta:
model = Event
fields = [
'title', 'start', 'end', 'body',
'webinar_link',
'webinar_code',
]

def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)

def save(self, commit=True):
event = super(EventForm, self).save(commit=False)
# Append f-string to the body field
webinar_link = self.cleaned_data.get('webinar_link', '')
webinar_code = self.cleaned_data.get('webinar_code', '')
event.body += f'<br><br><b>Meeting Join Link:</b> <a href="{webinar_link}" target="_blank">Click here to join</a><br><b>Meeting Join Code:</b> {webinar_code}'
if commit:
event.save()
return event
28 changes: 28 additions & 0 deletions hackathon/migrations/0054_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.1.13 on 2024-10-04 15:52

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('hackathon', '0053_auto_20240912_1527'),
]

operations = [
migrations.CreateModel(
name='Event',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('start', models.DateTimeField()),
('end', models.DateTimeField()),
('body', models.TextField(default='', max_length=500)),
('isReadOnly', models.BooleanField(default=True)),
('webinar_link', models.URLField(blank=True, null=True)),
('webinar_code', models.CharField(blank=True, max_length=50, null=True)),
('hackathon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events', to='hackathon.hackathon')),
],
),
]
17 changes: 17 additions & 0 deletions hackathon/migrations/0055_remove_event_isreadonly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.1.13 on 2024-10-08 13:58

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('hackathon', '0054_event'),
]

operations = [
migrations.RemoveField(
model_name='event',
name='isReadOnly',
),
]
26 changes: 26 additions & 0 deletions hackathon/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from accounts.models import CustomUser as User
from accounts.models import Organisation
from .lists import STATUS_TYPES_CHOICES
from datetime import timedelta

# Optional fields are ony set to deal with object deletion issues.
# If this isn't a problem, they can all be changed to required fields.
Expand Down Expand Up @@ -296,3 +297,28 @@ def __str__(self):

class Meta:
verbose_name_plural = "Hack project score categories"


class Event(models.Model):
"""
Model representing an event in the calendar.
"""
hackathon = models.ForeignKey('Hackathon', on_delete=models.CASCADE, related_name='events')
title = models.CharField(max_length=200)
start = models.DateTimeField()
end = models.DateTimeField()
body = models.TextField(max_length=500, default="")
webinar_link = models.URLField(blank=True, null=True)
webinar_code = models.CharField(max_length=50, blank=True, null=True)

def save(self, *args, **kwargs):
"""
If the end time is not set, it will be set to start time + 1 hour.
"""
if not self.end:
self.end = self.start + timedelta(hours=1)
super().save(*args, **kwargs)

def __str__(self):
return self.title
50 changes: 49 additions & 1 deletion hackathon/static/hackathon/css/hackathon.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,52 @@
font-size: 1rem;
} */

}
}

/* Custom popup styles */
.toastui-calendar-detail-container {
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
padding: 20px;
position: fixed;
z-index: 1000;
width: 300px;
/* Adjust as needed */
overflow: hidden;
word-wrap: break-word;
/* Ensure long words break within the container */
white-space: normal;
/* Allow normal wrapping */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.toastui-calendar-detail-container .toastui-calendar-icon {
display: none;
}
.toastui-calendar-floating-layer > div.toastui-calendar-event-detail-popup-slot > div > div.toastui-calendar-detail-container > div.toastui-calendar-popup-section.toastui-calendar-section-detail > div:nth-child(2) {
display: none;
}
.toastui-calendar-detail-container .toastui-calendar-section-button {
display: none;
}

/* Calendar next buttons */
#next-button,
#prev-button {
background-color: #fff;
color: #4A4A4F;
border: 1px solid #4A4A4F;
padding: 5px 5px;
text-align: center;
text-decoration: none;
font-weight: bold;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 5px;
}

60 changes: 60 additions & 0 deletions hackathon/templates/hackathon/change_event.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{% extends "base.html" %}
{% load static %}
{% load crispy_forms_tags %}

{% block css %}
<!-- XDSoft DateTimePicker -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.min.css"
integrity="sha256-DOS9W6NR+NFe1fUhEE0PGKY/fubbUCnOfTje2JMDw3Y=" crossorigin="anonymous"/>
{% endblock %}

{% block content %}

<section class="h-100">
<div class="row mb-3">
<div class="col-12">
{% if event %}
<h1>Edit Event</h1>
{% else %}
<h1>Create Event</h1>
{% endif %}
</div>
</div>

<form method="POST">
{% csrf_token %}
<div class="row">
<div class="col-12">
{{ form.title|as_crispy_field }}
</div>
<div class="col-12" >
{{ form.start|as_crispy_field }}
</div>
<div class="col-12" id="webinar_end_date">
{{ form.end|as_crispy_field }}
</div>
<div class="col-12">
{{ form.body|as_crispy_field }}
</div>
<div class="col-12">
{{ form.webinar_link|as_crispy_field }}
</div>
<div class="col-12">
{{ form.webinar_code|as_crispy_field }}
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
</section>

{% endblock %}

{% block js %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"
integrity="sha256-FEqEelWI3WouFOo2VWP/uJfs1y8KJ++FLh2Lbqc8SJk=" crossorigin="anonymous">
</script>
<script src="{% static 'js/datetimepicker.js' %}"></script>
{% endblock %}
30 changes: 30 additions & 0 deletions hackathon/templates/hackathon/hackathon_events.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends "base.html" %}

{% block content %}
<h2>{{ hackathon.display_name }} - Webinars</h2>
{% if events %}
<div class="card">
<div class="card-body">
<ul class="list-group">
{% for event in events %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<div>
<h5> {{ hackathon.display_name }} {{ event.title }}</h5>
<p>{{ event.start }}</p>
<p><a href="{{ event.webinar_link }}" target="_blank">Webinar Link </a></p>
<p>{{ event.body | safe }}</p>
</div>
<div>
<a href="{% url 'hackathon:change_event' hackathon.id event.id %}" class="btn btn-primary btn-sm">Edit</a>
<a href="{% url 'hackathon:delete_event' hackathon.id event.id %}" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this event?');">Delete</a>
</div>
</li>
{% endfor %}
</ul>
</div>
</div>
{% else %}
<p>No events found. <a href="{% url 'hackathon:change_event' hackathon.id %}">Add an event</a></p>
{% endif %}
<a href="{% url 'hackathon:change_event' hackathon.id %}" class="btn btn-primary mt-3">Add Event</a>
{% endblock %}
Loading

0 comments on commit 355429e

Please sign in to comment.