Skip to content
Snippets Groups Projects
Commit a3ef933c authored by Jan-Hendrik Willms's avatar Jan-Hendrik Willms Committed by David Siegfried
Browse files

allow pauses for consultation hours, fixes #925

Closes #925

Merge request studip/studip!521
parent 5cc27396
No related branches found
No related tags found
No related merge requests found
......@@ -158,7 +158,9 @@ class Consultation_AdminController extends ConsultationController
$this->getDateAndTime('end'),
Request::int('day-of-week'),
Request::int('interval'),
Request::int('duration')
Request::int('duration'),
Request::bool('pause') ? Request::int('pause_time') : null,
Request::bool('pause') ? Request::int('pause_duration') : null
);
if ($slot_count >= self::SLOT_COUNT_THRESHOLD && !Request::int('confirmed')) {
$this->flash['confirm-many'] = $slot_count;
......@@ -183,7 +185,11 @@ class Consultation_AdminController extends ConsultationController
$block->note = Request::get('note');
$block->size = Request::int('size', 1);
$block->createSlots(Request::int('duration'));
$block->createSlots(
Request::int('duration'),
Request::bool('pause') ? Request::int('pause_time') : null,
Request::bool('pause') ? Request::int('pause_duration') : null
);
$stored += $block->store();
// Store block responsibilites
......
......@@ -119,6 +119,25 @@ $intervals = [
<input required type="text" name="size" id="size"
min="1" max="50" value="<?= Request::int('size', 1) ?>">
</label>
<label>
<input type="checkbox" name="pause" value="1" data-shows=".pause-inputs" data-activates=".pause-inputs input">
<?= _('Pausen zwischen den Terminen einfügen?') ?>
</label>
<label class="col-3 pause-inputs">
<?= _('Eine Pause nach wie vielen Minuten einfügen?') ?>
<input type="number" name="pause_time"
value="<?= htmlReady(Request::int('pause_time', 45)) ?>"
min="1">
</label>
<label class="col-3 pause-inputs">
<?= _('Dauer der Pause in Minuten') ?>
<input type="number" name="pause_duration"
value="<?= Request::int('pause_duration', 15) ?>"
min="1">
</label>
</fieldset>
<? if ($responsible): ?>
......
......@@ -118,15 +118,17 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
/**
* Count generated blocks according to the given data.
*
* @param int $start Start of the time range as unix timestamp
* @param int $end End of the time range as unix timestamp
* @param int $week_day Day of the week the blocks should be created
* (0 = sunday, 1 = monday ...)
* @param int $interval Week interval (skip $interval weeks between
* blocks)
* @param int $duration Duration of a slot in minutes
* @param int $start Start of the time range as unix timestamp
* @param int $end End of the time range as unix timestamp
* @param int $week_day Day of the week the blocks should be
* created (0 = sunday, 1 = monday ...)
* @param int $interval Week interval (skip $interval weeks
* between blocks)
* @param int $duration Duration of a slot in minutes
* @param int|null $pause_time Create a pause after $pause_time minutes
* @param int|null $pause_duration Duration of the pause
*/
public static function countBlocks($start, $end, $week_day, $interval, $duration)
public static function countBlocks($start, $end, $week_day, $interval, $duration, $pause_time = null, $pause_duration = null)
{
$count = 0;
......@@ -147,9 +149,23 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
$block_start = strtotime("today {$start_time}", $current);
$block_end = strtotime("today {$end_time}", $current);
while ($block_start < $block_end) {
$count += 1;
$block_start = strtotime("+{$duration} minutes", $block_start);
$now = $block_start;
while ($now < $block_end) {
$is_in_pause = false;
if ($pause_time !== null) {
$is_in_pause = self::checkIfSlotIsInPause(
$now,
strtotime("+{$duration} minutes", $now),
$block_start,
$block_end,
$pause_time,
$pause_duration
);
}
if (!$is_in_pause) {
$count += 1;
}
$now = strtotime("+{$duration} minutes", $now);
}
}
......@@ -254,20 +270,35 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
* Creates individual slots according to the defined data and given
* duration.
*
* @param int $duration Duration of a slot in minutes
* @param int $duration Duration of a slot in minutes
* @param int|null $pause_time Create a pause after $pause_time minutes
* @param int|null $pause_duration Duration of the pause
*/
public function createSlots($duration)
public function createSlots($duration, int $pause_time = null, int $pause_duration = null)
{
$start = $this->start;
while ($start < $this->end) {
$slot = new ConsultationSlot();
$slot->block_id = $this->id;
$slot->start_time = $start;
$slot->end_time = strtotime("+{$duration} minutes", $start);
$now = $this->start;
while ($now < $this->end) {
$is_in_pause = false;
if ($pause_time !== null) {
$is_in_pause = self::checkIfSlotIsInPause(
$now,
strtotime("+{$duration} minutes", $now),
$this->start,
$this->end,
$pause_time,
$pause_duration
);
}
if (!$is_in_pause) {
$slot = new ConsultationSlot();
$slot->block_id = $this->id;
$slot->start_time = $now;
$slot->end_time = strtotime("+{$duration} minutes", $now);
$this->slots[] = $slot;
$this->slots[] = $slot;
}
$start = $slot->end_time;
$now = strtotime("+{$duration} minutes", $now);
}
}
......@@ -396,6 +427,36 @@ class ConsultationBlock extends SimpleORMap implements PrivacyObject
}
/**
* Checks if a given time span (defined by $begin and $end) is inside a
* defined pause of a block.
*
* @param int $begin
* @param int $end
* @param int $block_begin
* @param int $block_end
* @param int $pause_time
* @param int $pause_duration
*
* @return bool
*/
private static function checkIfSlotIsInPause($begin, $end, $block_begin, $block_end, $pause_time, $pause_duration): bool
{
$now = $block_begin;
while ($now < $block_end) {
$pause_begin = strtotime("+{$pause_time} minutes", $now);
$pause_end = strtotime("+{$pause_duration} minutes", $pause_begin);
if ($begin < $pause_end && $end > $pause_begin) {
return true;
}
$now = $pause_end;
}
return false;
}
/**
* @return string A string representation of the consultation block instance.
*/
......
......@@ -124,6 +124,32 @@ STUDIP.ready((event) => {
$('select[data-activates]', event.target).trigger('change');
});
//
$(document).on('change', '[data-hides],[data-shows]', function () {
if (!$(this).is(':checkbox,:radio')) {
return;
}
['hides', 'shows'].forEach((type) => {
var selector = $(this).data(type);
if (selector === undefined || $(this).prop('disabled')) {
return;
}
var state = $(this).prop('checked') || $(this).prop('indeterminate') || false;
$(selector).each(function() {
var condition = $(this).data(`${type}Condition`),
toggle = state && (!condition || $(condition).length > 0);
$(this)
.toggle(type === 'shows' ? toggle : !toggle)
.trigger('update.proxy');
});
});
});
STUDIP.ready(event => {
$('[data-hides],[data-shows]', event.target).trigger('change');
});
// Enable the user to set the checked state on a subset of related
// checkboxes by clicking the first checkbox of the subset and then
// clicking the last checkbox of the subset while holding down the shift
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment