mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Maintenance Windows: recurring now works overnight (#11389)
* Alert Rules use Carbon Use carbon for time queries, need to be careful of timezone quirks. Timestamps won't have that issue * Convert existing schedules to UTC * we only need start end... we already have start/end * Make AlertSchedule::isActive work * Table display working (and using Eloquent) * Schedule creation updated * WIP * use Eloquent mutators/accessors * recurring_day mutator/accessor * WIP UI * Fix SQL to handle outside times * fix up some ui issues * Convert alert-schedule to new style Improved sorting customization * fix whitespace * support sqlite * Fix schedule creation missing id * Fix Device::isUnderMaintenance() add location relation
This commit is contained in:
@@ -14,6 +14,8 @@ use Illuminate\Support\Str;
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
if (!Auth::user()->hasGlobalAdmin()) {
|
||||
header('Content-type: text/plain');
|
||||
die('ERROR: You need to be admin');
|
||||
@@ -34,7 +36,7 @@ if ($sub_type == 'new-maintenance') {
|
||||
|
||||
$title = mres($_POST['title']);
|
||||
$notes = mres($_POST['notes']);
|
||||
$recurring = mres($_POST['recurring']);
|
||||
$recurring = $_POST['recurring'] ? 1 : 0;
|
||||
$start_recurring_dt = mres($_POST['start_recurring_dt']);
|
||||
$end_recurring_dt = mres($_POST['end_recurring_dt']);
|
||||
$start_recurring_hr = mres($_POST['start_recurring_hr']);
|
||||
@@ -75,7 +77,7 @@ if ($sub_type == 'new-maintenance') {
|
||||
$message .= 'Please check end recurring date<br />';
|
||||
}
|
||||
} else {
|
||||
$end_recurring_dt = null;
|
||||
$end_recurring_dt = '9000-09-09';
|
||||
}
|
||||
|
||||
if (empty($start_recurring_hr)) {
|
||||
@@ -117,18 +119,27 @@ if ($sub_type == 'new-maintenance') {
|
||||
}
|
||||
|
||||
if (empty($message)) {
|
||||
if (empty($schedule_id)) {
|
||||
$schedule_id = dbInsert(array('recurring' => $recurring, 'start' => $start, 'end' => $end, 'start_recurring_dt' => $start_recurring_dt, 'end_recurring_dt' => $end_recurring_dt, 'start_recurring_hr' => $start_recurring_hr, 'end_recurring_hr' => $end_recurring_hr, 'recurring_day' => $recurring_day, 'title' => $title, 'notes' => $notes), 'alert_schedule');
|
||||
} else {
|
||||
dbUpdate(array('recurring' => $recurring, 'start' => $start, 'end' => $end, 'start_recurring_dt' => $start_recurring_dt, 'end_recurring_dt' => $end_recurring_dt, 'start_recurring_hr' => $start_recurring_hr, 'end_recurring_hr' => $end_recurring_hr, 'recurring_day' => $recurring_day, 'title' => $title, 'notes' => $notes), 'alert_schedule', '`schedule_id`=?', array($schedule_id));
|
||||
}
|
||||
$alert_schedule = \App\Models\AlertSchedule::findOrNew($schedule_id);
|
||||
$alert_schedule->title = $title;
|
||||
$alert_schedule->notes = $notes;
|
||||
$alert_schedule->recurring = $recurring;
|
||||
$alert_schedule->start = $start;
|
||||
$alert_schedule->end = $end;
|
||||
|
||||
if ($schedule_id > 0) {
|
||||
if ($recurring) {
|
||||
$alert_schedule->start_recurring_dt = $start_recurring_dt;
|
||||
$alert_schedule->start_recurring_hr = $start_recurring_hr;
|
||||
$alert_schedule->end_recurring_dt = $end_recurring_dt;
|
||||
$alert_schedule->end_recurring_hr = $end_recurring_hr;
|
||||
}
|
||||
$alert_schedule->save();
|
||||
|
||||
if ($alert_schedule->schedule_id > 0) {
|
||||
$items = array();
|
||||
$fail = 0;
|
||||
|
||||
if ($update == 1) {
|
||||
dbDelete('alert_schedulables', '`schedule_id`=?', array($schedule_id));
|
||||
dbDelete('alert_schedulables', '`schedule_id`=?', [$alert_schedule->schedule_id]);
|
||||
}
|
||||
|
||||
foreach ($_POST['maps'] as $target) {
|
||||
@@ -141,7 +152,7 @@ if ($sub_type == 'new-maintenance') {
|
||||
$target = substr($target, 1);
|
||||
}
|
||||
|
||||
$item = dbInsert(['schedule_id' => $schedule_id, 'alert_schedulable_type' => $type, 'alert_schedulable_id' => $target], 'alert_schedulables');
|
||||
$item = dbInsert(['schedule_id' => $alert_schedule->schedule_id, 'alert_schedulable_type' => $type, 'alert_schedulable_id' => $target], 'alert_schedulables');
|
||||
if ($notes && $type = 'device' && get_user_pref('add_schedule_note_to_device', false)) {
|
||||
$device_notes = dbFetchCell('SELECT `notes` FROM `devices` WHERE `device_id` = ?;', [$target]);
|
||||
$device_notes.= ((empty($device_notes)) ? '' : PHP_EOL) . date("Y-m-d H:i") . ' Alerts delayed: ' . $notes;
|
||||
@@ -159,7 +170,7 @@ if ($sub_type == 'new-maintenance') {
|
||||
dbDelete('alert_schedulables', '`item_id`=?', array($item));
|
||||
}
|
||||
|
||||
dbDelete('alert_schedule', '`schedule_id`=?', array($schedule_id));
|
||||
dbDelete('alert_schedule', '`schedule_id`=?', [$alert_schedule->schedule_id]);
|
||||
$message = 'Issue scheduling maintenance';
|
||||
} else {
|
||||
$status = 'ok';
|
||||
@@ -176,7 +187,7 @@ if ($sub_type == 'new-maintenance') {
|
||||
);
|
||||
} elseif ($sub_type == 'parse-maintenance') {
|
||||
$schedule_id = mres($_POST['schedule_id']);
|
||||
$schedule = dbFetchRow('SELECT * FROM `alert_schedule` WHERE `schedule_id`=?', array($schedule_id));
|
||||
$alert_schedule = \App\Models\AlertSchedule::findOrFail($schedule_id);
|
||||
$items = [];
|
||||
foreach (dbFetchRows('SELECT `alert_schedulable_type`, `alert_schedulable_id` FROM `alert_schedulables` WHERE `schedule_id`=?', [$schedule_id]) as $target) {
|
||||
$id = $target['alert_schedulable_id'];
|
||||
@@ -195,19 +206,9 @@ if ($sub_type == 'new-maintenance') {
|
||||
];
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'start' => $schedule['start'],
|
||||
'end' => $schedule['end'],
|
||||
'title' => $schedule['title'],
|
||||
'notes' => $schedule['notes'],
|
||||
'recurring' => $schedule['recurring'],
|
||||
'start_recurring_dt' => ($schedule['start_recurring_dt'] != '0000-00-00' ? $schedule['start_recurring_dt']: '1970-01-02 00:00:01'),
|
||||
'end_recurring_dt' => ($schedule['end_recurring_dt']!= '0000-00-00' ? $schedule['end_recurring_dt'] : '1970-01-02 00:00:01'),
|
||||
'start_recurring_hr' => substr($schedule['start_recurring_hr'], 0, 5),
|
||||
'end_recurring_hr' => substr($schedule['end_recurring_hr'], 0, 5),
|
||||
'recurring_day' => $schedule['recurring_day'],
|
||||
'targets' => $items,
|
||||
);
|
||||
$response = $alert_schedule->toArray();
|
||||
$response['recurring_day'] = $alert_schedule->getOriginal('recurring_day');
|
||||
$response['targets'] = $items;
|
||||
} elseif ($sub_type == 'del-maintenance') {
|
||||
$schedule_id = mres($_POST['del_schedule_id']);
|
||||
dbDelete('alert_schedule', '`schedule_id`=?', array($schedule_id));
|
||||
|
@@ -93,13 +93,13 @@ if (\Auth::user()->hasGlobalAdmin()) {
|
||||
<div class="form-group">
|
||||
<label for="recurring_day" class="col-sm-4 control-label">Only on weekday: </label>
|
||||
<div class="col-sm-8">
|
||||
<div style="float: left;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="1" />Mo</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="2" />Tu</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="3" />We</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="4" />Th</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="5" />Fr</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="6" />Sa</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" id="recurring_day" name="recurring_day[]" value="0" />Su</label></div>
|
||||
<div style="float: left;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="1" />Mo</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="2" />Tu</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="3" />We</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="4" />Th</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="5" />Fr</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="6" />Sa</label></div>
|
||||
<div style="float: left;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="7" />Su</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,7 +126,6 @@ $('#schedule-maintenance').on('hide.bs.modal', function (event) {
|
||||
$('#schedule_id').val('');
|
||||
$('#title').val('');
|
||||
$('#notes').val('');
|
||||
$('#recurring').val('');
|
||||
$('#start').val(moment().format('YYYY-MM-DD HH:mm')).data("DateTimePicker").maxDate(false).minDate(moment());
|
||||
$('#end').val(moment().add(1, 'hour').format('YYYY-MM-DD HH:mm')).data("DateTimePicker").maxDate(false).minDate(moment());
|
||||
var $startRecurringDt = $('#start_recurring_dt');
|
||||
@@ -138,7 +137,7 @@ $('#schedule-maintenance').on('hide.bs.modal', function (event) {
|
||||
|
||||
$('#start_recurring_hr').val('').data("DateTimePicker").minDate(false).maxDate(false);
|
||||
$('#end_recurring_hr').val('').data("DateTimePicker").minDate(false).maxDate(false);
|
||||
$('#recurring_day').prop('checked', false);
|
||||
$("input[name='recurring_day[]']").prop('checked', false);
|
||||
$("#recurring").bootstrapSwitch('state', false);
|
||||
$('#recurring').val(0);
|
||||
$('#norecurringgroup').show();
|
||||
@@ -184,7 +183,7 @@ $('#schedule-maintenance').on('show.bs.modal', function (event) {
|
||||
$('#end_recurring_dt').val('');
|
||||
$('#start_recurring_hr').val('');
|
||||
$('#end_recurring_hr').val('');
|
||||
$('#recurring_day').prop('checked', false);
|
||||
$("input[name='recurring_day[]']").prop('checked', false);
|
||||
$("#recurring").bootstrapSwitch('state', false);
|
||||
$('#recurring').val(0);
|
||||
}else{
|
||||
@@ -211,7 +210,7 @@ $('#schedule-maintenance').on('show.bs.modal', function (event) {
|
||||
$("input[name='recurring_day[]'][value="+checkedday+"]").prop('checked', true);
|
||||
});
|
||||
}else{
|
||||
$('#recurring_day').prop('checked', false);
|
||||
$("input[name='recurring_day[]']").prop('checked', false);
|
||||
}
|
||||
|
||||
$('#norecurringgroup').hide();
|
||||
|
@@ -31,8 +31,8 @@ if (Auth::user()->hasGlobalAdmin()) {
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-danger danger" id="sched-maintenance-removal" data-target="sched-maintenance-removal">Delete</button>
|
||||
<input type="hidden" name="del_schedule_id" id="del_schedule_id">
|
||||
<input type="hidden" name="type" id="type" value="schedule-maintenance">
|
||||
<input type="hidden" name="sub_type" id="sub_type" value="del-maintenance">
|
||||
<input type="hidden" name="type" value="schedule-maintenance">
|
||||
<input type="hidden" name="sub_type" value="del-maintenance">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -77,12 +77,7 @@ var grid = $("#alert-schedule").bootgrid({
|
||||
"<div class=\"col-sm-4 actionBar\"><p class=\"{{css.search}}\"></p><p class=\"{{css.actions}}\"></p></div></div></div>"
|
||||
},
|
||||
rowCount: [50, 100, 250, -1],
|
||||
post: function () {
|
||||
return {
|
||||
id: "alert-schedule",
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
url: "ajax/table/alert-schedule"
|
||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||
/* Executes after data is loaded and rendered */
|
||||
grid.find(".command-edit").on("click", function(e) {
|
||||
|
@@ -307,7 +307,8 @@ If `devices.ignore = 0` or `macros.device = 1` condition is is set and ignore al
|
||||
<script>
|
||||
$('[type="checkbox"]').bootstrapSwitch('offColor', 'danger');
|
||||
|
||||
$("#maintenance").click(function() {
|
||||
$("#maintenance").click(function(event) {
|
||||
event.preventDefault();
|
||||
var device_id = $(this).data("device_id");
|
||||
var title = '<?=display($device['hostname']);?>';
|
||||
var notes = '';
|
||||
|
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* LibreNMS
|
||||
*
|
||||
* Copyright (c) 2014 Neil Lathwood <https://github.com/laf/ http://www.lathwood.co.uk/fa>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version. Please see LICENSE.txt at the top level of
|
||||
* the source code distribution for details.
|
||||
*/
|
||||
|
||||
$where = 1;
|
||||
|
||||
$sql = " FROM `alert_schedule` AS S WHERE $where";
|
||||
if (!Auth::user()->hasGlobalRead()) {
|
||||
$param[] = Auth::id();
|
||||
}
|
||||
|
||||
if (isset($searchPhrase) && !empty($searchPhrase)) {
|
||||
$sql .= " AND (`S`.`title` LIKE '%$searchPhrase%' OR `S`.`start` LIKE '%$searchPhrase%' OR `S`.`end` LIKE '%$searchPhrase%')";
|
||||
}
|
||||
|
||||
$count_sql = "SELECT COUNT(`schedule_id`) $sql";
|
||||
$total = dbFetchCell($count_sql, $param);
|
||||
if (empty($total)) {
|
||||
$total = 0;
|
||||
}
|
||||
|
||||
if (isset($sort) && !empty($sort)) {
|
||||
list($sort_column, $sort_order) = explode(' ', trim($sort));
|
||||
if ($sort_column == 'status') {
|
||||
$sort_by_status = true;
|
||||
$sort = "`S`.`start` $sort_order";
|
||||
}
|
||||
} else {
|
||||
$sort = '`S`.`start` DESC ';
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY $sort";
|
||||
|
||||
if (isset($current)) {
|
||||
$limit_low = (($current * $rowCount) - ($rowCount));
|
||||
$limit_high = $rowCount;
|
||||
}
|
||||
|
||||
if ($rowCount != -1) {
|
||||
$sql .= " LIMIT $limit_low,$limit_high";
|
||||
}
|
||||
|
||||
$sql = "SELECT `S`.`schedule_id`, `S`.`recurring`, DATE_FORMAT(NOW(), '" . \LibreNMS\Config::get('dateformat.mysql.compact') . "') AS now, DATE_FORMAT(`S`.`start`, '" . \LibreNMS\Config::get('dateformat.mysql.compact') . "') AS `start`, DATE_FORMAT(`S`.`end`, '" . \LibreNMS\Config::get('dateformat.mysql.compact') . "') AS `end`, DATE_FORMAT(`S`.`start_recurring_dt`, '" . \LibreNMS\Config::get('dateformat.mysql.date') . "') AS `start_recurring_dt`, DATE_FORMAT(`S`.`end_recurring_dt`, '" . \LibreNMS\Config::get('dateformat.mysql.date') . "') AS `end_recurring_dt`, `S`.`start_recurring_hr`, `S`.`end_recurring_hr`, `S`.`recurring_day`, `S`.`title` $sql";
|
||||
|
||||
foreach (dbFetchRows($sql, $param) as $schedule) {
|
||||
$status = 0;
|
||||
if ($schedule['recurring'] == 0) {
|
||||
$start = strtotime($schedule['start']);
|
||||
$end = strtotime($schedule['end']);
|
||||
$now = strtotime($schedule['now']);
|
||||
if ($end < $now) {
|
||||
$status = 1;
|
||||
}
|
||||
|
||||
if ($now >= $start && $now < $end) {
|
||||
$status = 2;
|
||||
}
|
||||
} else {
|
||||
$start = strtotime($schedule['start_recurring_dt']);
|
||||
$end = $schedule['end_recurring_dt'] != '' && $schedule['end_recurring_dt'] != '0000-00-00' ? strtotime($schedule['end_recurring_dt'].' '. $schedule['end_recurring_hr']) : 0;
|
||||
$now = strtotime($schedule['now']);
|
||||
if ($end < $now && $end != 0) {
|
||||
$status =1;
|
||||
}
|
||||
if ($start <= $now && ($now <= $end || $end == 0)) {
|
||||
$status = 2;
|
||||
}
|
||||
}
|
||||
$table_rd = '';
|
||||
if ($schedule['recurring_day'] != '') {
|
||||
$array_days = array(
|
||||
0 => 'Su',
|
||||
1 => 'Mo',
|
||||
2 => 'Tu',
|
||||
3 => 'We',
|
||||
4 => 'Th',
|
||||
5 => 'Fr',
|
||||
6 => 'Sa'
|
||||
);
|
||||
$array_rd = explode(',', $schedule['recurring_day']);
|
||||
|
||||
foreach ($array_rd as $key_rd => $val_rd) {
|
||||
if (array_key_exists($val_rd, $array_days)) {
|
||||
$table_rd .= $table_rd != '' ? ','. $array_days[$val_rd] : $array_days[$val_rd];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$response[] = array(
|
||||
'title' => $schedule['title'],
|
||||
'recurring' => $schedule['recurring'] == 1 ? 'yes' : 'no',
|
||||
'start' => $schedule['recurring'] == 1 ? '' : $schedule['start'],
|
||||
'end' => $schedule['recurring'] == 1 ? '' : $schedule['end'],
|
||||
'start_recurring_dt' => $schedule['recurring'] == 0 || $schedule['start_recurring_dt'] == '0000-00-00' ? '' : $schedule['start_recurring_dt'],
|
||||
'end_recurring_dt' => $schedule['recurring'] == 0 || $schedule['end_recurring_dt'] == '0000-00-00' ? '' : $schedule['end_recurring_dt'],
|
||||
'start_recurring_hr' => $schedule['recurring'] == 0 ? '' : substr($schedule['start_recurring_hr'], 0, 5),
|
||||
'end_recurring_hr' => $schedule['recurring'] == 0 ? '' : substr($schedule['end_recurring_hr'], 0, 5),
|
||||
'recurring_day' => $schedule['recurring'] == 0 ? '' : $table_rd,
|
||||
'id' => $schedule['schedule_id'],
|
||||
'status' => $status,
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($sort_by_status) && $sort_by_status) {
|
||||
if ($sort_order == 'asc') {
|
||||
usort($response, function ($a, $b) {
|
||||
return $a['status'] - $b['status'];
|
||||
});
|
||||
} else {
|
||||
usort($response, function ($a, $b) {
|
||||
return $b['status'] - $a['status'];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$output = array(
|
||||
'current' => $current,
|
||||
'rowCount' => $rowCount,
|
||||
'rows' => $response,
|
||||
'total' => $total,
|
||||
);
|
||||
echo _json_encode($output);
|
Reference in New Issue
Block a user