Skip to content

Commit

Permalink
appointment end should be determined by start + duration
Browse files Browse the repository at this point in the history
  • Loading branch information
bbonf committed Nov 14, 2024
1 parent 914daae commit 8a44b48
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 20 deletions.
1 change: 0 additions & 1 deletion babex-vue/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ class GenericApiPart<T> extends ApiPart {

interface AppointmentCreate {
start: Date,
end: Date,
experiment: number,
leader: number,
participant: number,
Expand Down
6 changes: 4 additions & 2 deletions babex-vue/src/components/agenda/AgendaCalendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// optional experiment id for limiting feeds
experiment?: number,
scheduling?: boolean,
duration?: number,
}>();
// from https://stackoverflow.com/a/64090995
Expand Down Expand Up @@ -130,7 +130,9 @@
allDaySlot: false,
slotMinTime: "07:00:00",
slotMaxTime: "20:00:00",
slotDuration: props.scheduling ? "00:15:00" : "00:30:00",
slotDuration: {minutes: props.duration ?? 30},
defaultTimedEventDuration: {minutes: props.duration},
forceEventDuration: props.duration ? true : false,
eventTimeFormat: {
hour: '2-digit',
minute: '2-digit',
Expand Down
2 changes: 1 addition & 1 deletion babex-vue/src/components/agenda/AppointmentForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
<DateTimePicker class="appointment-start" v-model="form.start" :readonly="hasOutcome()" />

<div>{{ _('To:') }}</div>
<DateTimePicker class="appointment-end" v-model="form.end" :readonly="hasOutcome()" />
<DateTimePicker class="appointment-end" v-model="form.end" :readonly="true" />

<div>
<label>{{ _('Comments:') }}</label>
Expand Down
20 changes: 9 additions & 11 deletions babex-vue/src/components/invite/CallHome.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { _ } from '@/util';
import {defineProps, ref} from 'vue';
import {defineProps, ref, computed} from 'vue';
import AgendaCalendar from '../agenda/AgendaCalendar.vue';
import {babexApi} from '../../api';
import {Call} from '../../types';
Expand All @@ -10,7 +10,7 @@
const props = defineProps<{
participant: {id: number, name: string},
experiment: {id: number, name: string},
experiment: {id: number, name: string, session_duration: number},
leaders: {id: number, name: string}[],
statuses: { [id: string]: string},
call: Call,
Expand All @@ -32,7 +32,7 @@
// event start and end times saved as separate refs because
// our DateTimePicker doesn't play nicely with fullcalendar's event object
const eventStart = ref<Date|null>(null);
const eventEnd = ref<Date|null>(null);
const eventEnd = computed(() => new Date(eventStart.value.getTime() + 60 * 1000 * props.experiment.session_duration));
const callStatus = ref<string|null>(null);
const comment = ref('');
Expand Down Expand Up @@ -72,13 +72,12 @@
}
function confirm() {
if(!event.value || !eventStart.value || !eventEnd.value) {
if(!event.value || !eventStart.value) {
return;
}
babexApi.call.appointment.create({
start: eventStart.value,
end: eventEnd.value,
experiment: props.experiment.id,
participant: props.participant.id,
leader: confirmationForm.value.leader,
Expand Down Expand Up @@ -112,11 +111,9 @@
}
event.value = calendar.value?.calendar.getApi().addEvent({
start: selectionInfo.start,
end: selectionInfo.end,
startEditable: true
});
eventStart.value = selectionInfo.start;
eventEnd.value = selectionInfo.end;
eventStart.value = event.value.start;
}
else {
step.value = 1;
Expand Down Expand Up @@ -170,6 +167,7 @@
function complete() {
location.href = props.completeUrl;
}
</script>

<template>
Expand Down Expand Up @@ -204,15 +202,15 @@
<div class="modal-dialog modal-dialog-centered modal-lg">
<div v-if="step < 2" class="modal-content">
<div class="modal-body">
<AgendaCalendar ref="calendar" @select="onSelect" :start="start" :end="end" :experiment="experiment.id" :scheduling="true"></AgendaCalendar>
<AgendaCalendar ref="calendar" @select="onSelect" :start="start" :end="end" :experiment="experiment.id" :duration="experiment.session_duration"></AgendaCalendar>
</div>
<div class="modal-footer">
<button @click="reset()" type="button" class="btn btn-secondary" :disabled="step < 1">{{ _('Back') }}</button>
<button @click="step = 2" type="button" class="btn btn-primary" :disabled="event==null">{{ _('Next') }}</button>
<button @click="modalVisible = false" type="button" class="btn btn-secondary">{{ _('Cancel') }}</button>
</div>
</div>
<div v-if="step === 2 && eventStart && eventEnd" class="modal-content">
<div v-if="step === 2 && eventStart" class="modal-content">
<div class="modal-body">
<h2>{{ _('Appointment details') }}</h2>
<table class="table mt-3">
Expand All @@ -225,7 +223,7 @@
</tr>
<tr>
<th>{{ _('To') }}</th>
<td><DateTimePicker v-model="eventEnd" /></td>
<td><DateTimePicker :readonly="true" v-model="eventEnd" /></td>
</tr>
</table>

Expand Down
2 changes: 1 addition & 1 deletion lab/agenda/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def perform_update(self, serializer):
updated_timeslot = updated.timeslot

# check if we should inform the participant about changed time
if original_timeslot.start != updated_timeslot.start or original_timeslot.end != updated_timeslot.end:
if original_timeslot.start != updated_timeslot.start:
send_appointment_mail(updated, prepare_appointment_mail(updated))


Expand Down
4 changes: 4 additions & 0 deletions lab/experiments/models/appointment_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ def save(self, *args, **kwargs):
# verify that the leader is valid
if self.leader not in self.experiment.leaders.all():
raise ValueError("Leader {} is not part of experiment {}".format(self.leader, self.experiment))

# make sure the end time is correct
self.end = self.start + timedelta(minutes=self.experiment.session_duration)
self.timeslot.save()

super().save(*args, **kwargs)

def __str__(self):
Expand Down
5 changes: 3 additions & 2 deletions lab/experiments/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Meta:
contact_phone = serializers.ReadOnlyField(source="leader.phonenumber")

start = serializers.DateTimeField()
end = serializers.DateTimeField()
end = serializers.ReadOnlyField()

session_duration = serializers.ReadOnlyField(source="experiment.session_duration")

Expand All @@ -70,6 +70,7 @@ class Meta:
"id",
"name",
"duration",
"session_duration",
"task_description",
"location",
"leaders",
Expand Down Expand Up @@ -104,6 +105,6 @@ class Meta:
contact_phone = serializers.ReadOnlyField(source="leader.phonenumber")

start = serializers.DateTimeField()
end = serializers.DateTimeField()
end = serializers.ReadOnlyField()

session_duration = serializers.ReadOnlyField(source="experiment.session_duration")
4 changes: 2 additions & 2 deletions lab/integration_tests/test_experiments.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ def test_create_experiment(page, as_admin, sample_leader, sample_location):

page.get_by_role("link", name="Create experiment").click()
page.get_by_role("textbox", name="Name").fill("Experiment name")
page.get_by_role("textbox", name="Task duration").fill("10")
page.get_by_role("textbox", name="Session duration").fill("25")
page.get_by_role("spinbutton", name="Task duration").fill("10")
page.get_by_role("spinbutton", name="Session duration").fill("25")
page.get_by_role("spinbutton", name="Recruitment target").fill("30")

page.locator('select[name="location"]').select_option(sample_location.name)
Expand Down

0 comments on commit 8a44b48

Please sign in to comment.