aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/consultation/admin.php14
-rw-r--r--app/views/consultation/admin/edit.php2
-rw-r--r--lib/models/ConsultationBlock.php2
-rw-r--r--resources/assets/stylesheets/scss/forms.scss5
-rw-r--r--resources/vue/components/ConsultationCreator.vue67
-rw-r--r--resources/vue/components/Timepicker.vue5
6 files changed, 62 insertions, 33 deletions
diff --git a/app/controllers/consultation/admin.php b/app/controllers/consultation/admin.php
index 8699349..21507ed 100644
--- a/app/controllers/consultation/admin.php
+++ b/app/controllers/consultation/admin.php
@@ -199,22 +199,27 @@ class Consultation_AdminController extends ConsultationController
try {
$interval = Request::int('interval');
$start = $this->getDateAndTime('start');
- $end = $this->getDateAndTime($interval === 0 ? 'start' : 'end', 'end');
+ $end = $this->getDateAndTime($interval <= 0 ? 'start' : 'end', 'end');
if (date('Hi', $end) <= date('Hi', $start)) {
throw new InvalidArgumentException(_('Die Endzeit liegt vor der Startzeit!'));
}
$dow = Request::int('day-of-week');
- if ($interval === 0) {
+ if ($interval <= 0) {
$dow = date('w', $start);
}
// Determine duration of a slot and pause times
$duration = Request::int('duration');
+
+ if ($duration === null && $interval === -1) {
+ $duration = (int) (($end - $start) / 60);
+ }
+
$pause_time = Request::bool('pause') ? Request::int('pause_time') : null;
$pause_duration = Request::bool('pause') ? Request::int('pause_duration') : null;
- if ($pause_time && $pause_time < $duration) {
+ if ($interval >= 0 && $pause_time && $pause_time < $duration) {
throw new InvalidArgumentException(_('Die definierte Zeit bis zur Pause ist kleiner als die Dauer eines Termins.'));
}
@@ -231,6 +236,7 @@ class Consultation_AdminController extends ConsultationController
$pause_time,
$pause_duration
);
+
if ($slot_count >= self::SLOT_COUNT_THRESHOLD && !Request::int('confirmed')) {
$this->flash['confirm-many'] = $slot_count;
throw new Exception('', -1);
@@ -257,7 +263,7 @@ class Consultation_AdminController extends ConsultationController
$block->lock_time = Request::int('lock_time');
$block->consecutive = Request::bool('consecutive', false);
- $slots = $block->createSlots(Request::int('duration'), $pause_time, $pause_duration);
+ $slots = $block->createSlots($duration, $pause_time, $pause_duration);
if (count($slots) === 0) {
continue;
}
diff --git a/app/views/consultation/admin/edit.php b/app/views/consultation/admin/edit.php
index f9b416a..1fd0cf1 100644
--- a/app/views/consultation/admin/edit.php
+++ b/app/views/consultation/admin/edit.php
@@ -45,7 +45,7 @@
<? endif; ?>
<label>
- <?= _('Maximale Teilnehmerzahl') ?>
+ <?= _('Maximale Teilnehmendenzahl') ?>
<?= tooltipIcon(_('Falls Sie mehrere Personen zulassen wollen (wie z.B. zu einer Klausureinsicht), so geben Sie hier die maximale Anzahl an Personen an, die sich anmelden dürfen.')) ?>
<input required type="text" name="size" id="size"
min="1" max="50" value="<?= $block->size ?>">
diff --git a/lib/models/ConsultationBlock.php b/lib/models/ConsultationBlock.php
index cde8f77..3e5de6e 100644
--- a/lib/models/ConsultationBlock.php
+++ b/lib/models/ConsultationBlock.php
@@ -212,7 +212,7 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
);
}
- if (!$interval) {
+ if ($interval <= 0) {
break;
}
diff --git a/resources/assets/stylesheets/scss/forms.scss b/resources/assets/stylesheets/scss/forms.scss
index 2aa105f..d847dbe 100644
--- a/resources/assets/stylesheets/scss/forms.scss
+++ b/resources/assets/stylesheets/scss/forms.scss
@@ -637,7 +637,10 @@ form.inline {
> :not(footer[data-dialog-button]) {
flex: 0;
- margin-bottom: auto;
+
+ &:last-of-type {
+ margin-bottom: auto;
+ }
}
footer[data-dialog-button] {
diff --git a/resources/vue/components/ConsultationCreator.vue b/resources/vue/components/ConsultationCreator.vue
index 163e238..56f9726 100644
--- a/resources/vue/components/ConsultationCreator.vue
+++ b/resources/vue/components/ConsultationCreator.vue
@@ -31,8 +31,8 @@
<label :class="{'col-3': !isSingleDay}">
<span class="required">{{ $gettext('Intervall') }}</span>
<select required name="interval" v-model.number="interval">
- <option v-for="(label, value) in intervals" :key="value" :value="value">
- {{ label }}
+ <option v-for="item in intervals" :key="item.key" :value="item.key">
+ {{ item.label }}
</option>
</select>
</label>
@@ -71,7 +71,7 @@
></Datepicker>
</label>
- <label for="start-time" class="col-3">
+ <label for="start-time" :class="{'col-3': !isSingleDate}">
<span class="required">{{ $gettext('Von') }}</span>
<Timepicker name="start-time"
@@ -80,7 +80,7 @@
></Timepicker>
</label>
- <label for="ende_hour" class="col-3">
+ <label for="ende_hour" :class="{'col-3': !isSingleDate}">
<span class="required">{{ $gettext('Bis') }}</span>
<Timepicker name="end-time"
@@ -89,26 +89,26 @@
></Timepicker>
</label>
- <label class="col-3">
+ <label class="col-3" v-if="!isSingleDate">
<span class="required">{{ $gettext('Dauer eines Termins in Minuten') }}</span>
<input required type="number" name="duration" min="1"
v-model="duration">
</label>
- <label class="col-3">
- {{ $gettext('Maximale Teilnehmerzahl') }}
+ <label :class="{'col-3': !isSingleDate}">
+ {{ $gettext('Maximale Teilnehmendenzahl') }}
<StudipTooltipIcon :text="$gettext('Falls Sie mehrere Personen zulassen wollen (wie z.B. zu einer Klausureinsicht), so geben Sie hier die maximale Anzahl an Personen an, die sich anmelden dürfen.')"></StudipTooltipIcon>
<input required type="text" name="size" id="size" min="1" max="50"
v-model="size">
</label>
- <label>
+ <label v-if="!isSingleDate">
<input type="checkbox" name="pause" value="1"
v-model="pause">
{{ $gettext('Pausen zwischen den Terminen einfügen?') }}
</label>
- <label class="col-3" v-if="pause">
+ <label class="col-3" v-if="!isSingleDate && pause">
{{ $gettext('Eine Pause nach wie vielen Minuten einfügen?') }}
<input type="number" name="pause_time" min="1"
v-model="pauseTime">
@@ -123,16 +123,16 @@
<label>
<input type="checkbox" name="lock" value="1"
v-model="lock">
- {{ $gettext('Termine für Buchungen sperren?') }}
+ {{ isSingleDate ? $gettext('Termin für Buchungen sperren?') : $gettext('Termin für Buchungen sperren?') }}
</label>
<label v-if="lock">
- {{ $gettext('Wieviele Stunden vor Beginn des Blocks sollen die Termine für Buchungen gesperrt werden?') }}
+ {{ isSingleDate ? $gettext('Wieviele Stunden vor Beginn des Blocks soll der Termin für Buchungen gesperrt werden?') : $gettext('Wieviele Stunden vor Beginn des Blocks sollen die Termine für Buchungen gesperrt werden?') }}
<input type="number" name="lock_time" min="1"
v-model="lockTime">
</label>
- <label>
+ <label v-if="!isSingleDate">
<input type="checkbox" name="consecutive" value="1"
v-model="consecutive">
{{ $gettext('Termine innerhalb der Blöcke nur fortlaufend vergeben') }}
@@ -204,14 +204,14 @@
<legend>{{ $gettext('Weitere Einstellungen') }}</legend>
<label>
- {{ $gettext('Information zu den Terminen in diesem Block') }}
+ {{ isSingleDate ? $gettext('Information zu diesem Termin') : $gettext('Information zu den Terminen in diesem Block') }}
<textarea name="note" v-model="note"></textarea>
</label>
<label>
<input type="checkbox" name="calender-events" value="1"
v-model="calendarEvents">
- {{ $gettext('Die freien Termine auch im Kalender markieren') }}
+ {{ isSingleDate ? $gettext('Den freien Termin auch im Kalender markieren') : $gettext('Die freien Termine auch im Kalender markieren') }}
</label>
<label v-if="isCourse">
@@ -370,13 +370,14 @@ export default {
];
},
intervals() {
- return {
- 0: this.$gettext('einmalig (ohne Wiederholung)'),
- 1: this.$gettext('wöchentlich'),
- 2: this.$gettext('zweiwöchentlich'),
- 3: this.$gettext('dreiwöchentlich'),
- 4: this.$gettext('monatlich'),
- };
+ return [
+ {key: -1, label: this.$gettext('Einzeltermin')},
+ {key: 0, label: this.$gettext('einmalig (ohne Wiederholung)')},
+ {key: 1, label: this.$gettext('wöchentlich')},
+ {key: 2, label: this.$gettext('zweiwöchentlich')},
+ {key: 3, label: this.$gettext('dreiwöchentlich')},
+ {key: 4, label: this.$gettext('monatlich')},
+ ];
},
isCourse() {
return this.rangeType === 'Course';
@@ -385,7 +386,11 @@ export default {
return this.rangeType === 'Institute';
},
isSingleDay() {
- return this.interval === 0;
+ return this.interval === 0
+ || this.interval === -1;
+ },
+ isSingleDate() {
+ return this.interval === -1;
},
needsConfirmation() {
return this.slotCount > this.slotCountThreshold;
@@ -438,11 +443,11 @@ export default {
errors.push(this.$gettext('Die Endzeit liegt vor der Startzeit!'));
}
- if (this.interval > 0 && this.compareDates(this.startDate, this.endDate, '>')) {
+ if (!this.isSingleDay && this.compareDates(this.startDate, this.endDate, '>')) {
errors.push(this.$gettext('Das Enddatum liegt vor dem Startdatum!'));
}
- if (this.pauseTime && this.pauseTime < this.duration) {
+ if (!this.isSingleDate && this.pauseTime && this.pauseTime < this.duration) {
errors.push(this.$gettext('Die definierte Zeit bis zur Pause ist kleiner als die Dauer eines Termins.'));
}
@@ -475,10 +480,20 @@ export default {
}
},
watch: {
- interval(current) {
- if (current === 0) {
+ interval(current, previous) {
+ if (current === 0 || current === -1) {
this.endDate = new Date(this.startDate);
}
+
+ if (current === -1) {
+ const start = this.combineDateAndTime(this.startDate, this.startTime);
+ const end = this.combineDateAndTime(this.endDate, this.endTime);
+ this.duration = Math.floor((end - start) / 1000 / 60);
+ }
+
+ if (current !== -1 && previous === -1) {
+ this.duration = 15;
+ }
},
recalculationProperty: {
handler() {
diff --git a/resources/vue/components/Timepicker.vue b/resources/vue/components/Timepicker.vue
index e0b0feb..d3a1ec6 100644
--- a/resources/vue/components/Timepicker.vue
+++ b/resources/vue/components/Timepicker.vue
@@ -35,3 +35,8 @@ export default {
}
}
</script>
+<style scoped>
+input[type="time"]::-webkit-calendar-picker-indicator {
+ display: none;
+}
+</style>