diff --git a/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue b/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue index 3c94e2d38e9d7a7f5d689e98a568e4a0d7261691..2ccff5dca6f3252cd89dc7721dc1e5f70aeed6ed 100644 --- a/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue +++ b/aleksis/core/frontend/components/calendar/personal_event/PersonalEventDialog.vue @@ -60,7 +60,7 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v </template> <!-- eslint-disable-next-line vue/valid-v-slot --> - <template #datetimeStart.field="{ attrs, on }"> + <template #datetimeStart.field="{ attrs, on, item }"> <v-slide-y-transition appear> <div aria-required="true"> <date-time-field @@ -69,13 +69,14 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v v-bind="attrs" v-on="on" required + :max="item.datetimeEnd" /> </div> </v-slide-y-transition> </template> <!-- eslint-disable-next-line vue/valid-v-slot --> - <template #datetimeEnd.field="{ attrs, on }"> + <template #datetimeEnd.field="{ attrs, on, item }"> <v-slide-y-transition appear> <div aria-required="true"> <date-time-field @@ -84,6 +85,9 @@ import CollapseTriggerButton from "../../generic/buttons/CollapseTriggerButton.v v-bind="attrs" v-on="on" required + :min=" + $parseISODate(item.datetimeStart).plus({ minutes: 1 }).toISO() + " /> </div> </v-slide-y-transition> diff --git a/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py b/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py new file mode 100644 index 0000000000000000000000000000000000000000..cd1620e7d5910bbc79d76197f1fe8b622fd280c5 --- /dev/null +++ b/aleksis/core/migrations/0071_constrain_calendar_event_starting_before_ending.py @@ -0,0 +1,23 @@ +from django.db import migrations, models +from django.db.models import F, Q + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0070_oauth_token_checksum'), + ] + + operations = [ + migrations.AddConstraint( + model_name='calendarevent', + constraint=models.CheckConstraint(check=Q(datetime_end__gt=F('datetime_start')), + name="datetime_start_before_end" + ), + ), + migrations.AddConstraint( + model_name='calendarevent', + constraint=models.CheckConstraint(check=Q(date_end__gt=F('date_start')), + name="date_start_before_end" + ), + ), + ] diff --git a/aleksis/core/models.py b/aleksis/core/models.py index 6a813fa84be2a47dcfe8ce4bfe73f0d6376c1f7f..c02ec1548928f459347df404d6b1a129e9924dc3 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -15,7 +15,7 @@ from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator from django.db import models -from django.db.models import Q, QuerySet +from django.db.models import F, Q, QuerySet from django.dispatch import receiver from django.forms.widgets import Media from django.http import HttpRequest @@ -1709,6 +1709,12 @@ class CalendarEvent(CalendarEventMixin, ExtensiblePolymorphicModel, RecurrenceMo check=~Q(datetime_end__isnull=True, date_end__isnull=True), name="datetime_end_or_date_end", ), + models.CheckConstraint( + check=Q(datetime_end__gt=F("datetime_start")), name="datetime_start_before_end" + ), + models.CheckConstraint( + check=Q(date_end__gt=F("date_start")), name="date_start_before_end" + ), models.CheckConstraint( check=~(Q(datetime_start__isnull=False, timezone="") & ~Q(recurrences="")), name="timezone_if_datetime_start_and_recurring",