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:
@@ -34,6 +34,7 @@
|
|||||||
namespace LibreNMS\Alert;
|
namespace LibreNMS\Alert;
|
||||||
|
|
||||||
use App\Models\Device;
|
use App\Models\Device;
|
||||||
|
use Carbon\Carbon;
|
||||||
use LibreNMS\Alert\AlertUtil;
|
use LibreNMS\Alert\AlertUtil;
|
||||||
use LibreNMS\Alert\AlertDB;
|
use LibreNMS\Alert\AlertDB;
|
||||||
use LibreNMS\Enum\AlertState;
|
use LibreNMS\Enum\AlertState;
|
||||||
@@ -113,7 +114,7 @@ class AlertRules
|
|||||||
if (is_null($current_state)) {
|
if (is_null($current_state)) {
|
||||||
dbInsert(array('state' => AlertState::ACTIVE, 'device_id' => $device_id, 'rule_id' => $rule['id'], 'open' => 1,'alerted' => 0), 'alerts');
|
dbInsert(array('state' => AlertState::ACTIVE, 'device_id' => $device_id, 'rule_id' => $rule['id'], 'open' => 1,'alerted' => 0), 'alerts');
|
||||||
} else {
|
} else {
|
||||||
dbUpdate(['state' => AlertState::ACTIVE, 'open' => 1, 'timestamp' => array('NOW()')], 'alerts', 'device_id = ? && rule_id = ?', [$device_id, $rule['id']]);
|
dbUpdate(['state' => AlertState::ACTIVE, 'open' => 1, 'timestamp' => Carbon::now()->timestamp], 'alerts', 'device_id = ? && rule_id = ?', [$device_id, $rule['id']]);
|
||||||
}
|
}
|
||||||
c_echo(PHP_EOL . 'Status: %rALERT');
|
c_echo(PHP_EOL . 'Status: %rALERT');
|
||||||
}
|
}
|
||||||
@@ -126,7 +127,7 @@ class AlertRules
|
|||||||
if (is_null($current_state)) {
|
if (is_null($current_state)) {
|
||||||
dbInsert(['state' => AlertState::RECOVERED, 'device_id' => $device_id, 'rule_id' => $rule['id'], 'open' => 1, 'alerted' => 0], 'alerts');
|
dbInsert(['state' => AlertState::RECOVERED, 'device_id' => $device_id, 'rule_id' => $rule['id'], 'open' => 1, 'alerted' => 0], 'alerts');
|
||||||
} else {
|
} else {
|
||||||
dbUpdate(['state' => AlertState::RECOVERED, 'open' => 1, 'note' => '', 'timestamp' => array('NOW()')], 'alerts', 'device_id = ? && rule_id = ?', [$device_id, $rule['id']]);
|
dbUpdate(['state' => AlertState::RECOVERED, 'open' => 1, 'note' => '', 'timestamp' => Carbon::now()->timestamp], 'alerts', 'device_id = ? && rule_id = ?', [$device_id, $rule['id']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
c_echo(PHP_EOL . 'Status: %gOK');
|
c_echo(PHP_EOL . 'Status: %gOK');
|
||||||
|
@@ -27,6 +27,7 @@ namespace LibreNMS\Alert;
|
|||||||
|
|
||||||
use App\Models\Device;
|
use App\Models\Device;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use DeviceCache;
|
||||||
use LibreNMS\Config;
|
use LibreNMS\Config;
|
||||||
use PHPMailer\PHPMailer\PHPMailer;
|
use PHPMailer\PHPMailer\PHPMailer;
|
||||||
|
|
||||||
@@ -196,8 +197,7 @@ class AlertUtil
|
|||||||
*/
|
*/
|
||||||
public static function isMaintenance($device_id)
|
public static function isMaintenance($device_id)
|
||||||
{
|
{
|
||||||
$device = Device::find($device_id);
|
return DeviceCache::get($device_id)->isUnderMaintenance();
|
||||||
return !is_null($device) && $device->isUnderMaintenance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -453,7 +453,7 @@ class RunAlerts
|
|||||||
$noacc = false;
|
$noacc = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AlertUtil::isMaintenance($alert['device_id']) > 0) {
|
if (AlertUtil::isMaintenance($alert['device_id'])) {
|
||||||
$noiss = true;
|
$noiss = true;
|
||||||
$noacc = true;
|
$noacc = true;
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,12 @@ use Illuminate\Support\Collection;
|
|||||||
|
|
||||||
abstract class PaginatedAjaxController extends Controller
|
abstract class PaginatedAjaxController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Default sort, column => direction
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $default_sort = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base rules for this controller.
|
* Base rules for this controller.
|
||||||
*
|
*
|
||||||
@@ -88,6 +94,18 @@ abstract class PaginatedAjaxController extends Controller
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines sortable fields. The incoming sort field should be the key, the sql column or DB::raw() should be the value
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
|
*/
|
||||||
|
protected function sortFields($request)
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format an item for display. Default is pass-through
|
* Format an item for display. Default is pass-through
|
||||||
*
|
*
|
||||||
@@ -148,9 +166,14 @@ abstract class PaginatedAjaxController extends Controller
|
|||||||
*/
|
*/
|
||||||
protected function sort($request, $query)
|
protected function sort($request, $query)
|
||||||
{
|
{
|
||||||
$sort = $request->get('sort', []);
|
$columns = $this->sortFields($request);
|
||||||
|
|
||||||
|
$sort = $request->get('sort', $this->default_sort);
|
||||||
|
|
||||||
foreach ($sort as $column => $direction) {
|
foreach ($sort as $column => $direction) {
|
||||||
$query->orderBy($column, $direction);
|
if (isset($columns[$column])) {
|
||||||
|
$query->orderBy($columns[$column], $direction == 'desc' ? 'desc' : 'asc');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
|
101
app/Http/Controllers/Table/AlertScheduleController.php
Normal file
101
app/Http/Controllers/Table/AlertScheduleController.php
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* AlertScheduleController.php
|
||||||
|
*
|
||||||
|
* -Description-
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* @package LibreNMS
|
||||||
|
* @link http://librenms.org
|
||||||
|
* @copyright 2020 Tony Murray
|
||||||
|
* @author Tony Murray <murraytony@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Table;
|
||||||
|
|
||||||
|
use App\Models\AlertSchedule;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use DB;
|
||||||
|
|
||||||
|
class AlertScheduleController extends TableController
|
||||||
|
{
|
||||||
|
protected $default_sort = ['title' => 'asc', 'start' => 'asc'];
|
||||||
|
|
||||||
|
protected function baseQuery($request)
|
||||||
|
{
|
||||||
|
return AlertSchedule::query();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function searchFields($request)
|
||||||
|
{
|
||||||
|
return['title', 'start', 'end'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function sortFields($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'start_recurring_dt' => DB::raw('DATE(`start`)'),
|
||||||
|
'start_recurring_ht' => DB::raw('TIME(`start`)'),
|
||||||
|
'end_recurring_dt' => DB::raw('DATE(`end`)'),
|
||||||
|
'end_recurring_ht' => DB::raw('TIME(`end`)'),
|
||||||
|
'title' => 'title',
|
||||||
|
'recurring' => 'recurring',
|
||||||
|
'start' => 'start',
|
||||||
|
'end' => 'end',
|
||||||
|
'status' => DB::raw("end < '" . Carbon::now('UTC') ."'"), // only partition lapsed
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param AlertSchedule $schedule
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function formatItem($schedule)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'title' => $schedule->title,
|
||||||
|
'notes' => $schedule->notes,
|
||||||
|
'id' => $schedule->schedule_id,
|
||||||
|
'start' => $schedule->recurring ? '' : $schedule->start->toDateTimeString('minutes'),
|
||||||
|
'end' => $schedule->recurring ? '' : $schedule->end->toDateTimeString('minutes'),
|
||||||
|
'start_recurring_dt' => $schedule->recurring ? $schedule->start_recurring_dt : '',
|
||||||
|
'start_recurring_hr' => $schedule->recurring ? $schedule->start_recurring_hr : '',
|
||||||
|
'end_recurring_dt' => $schedule->recurring ? $schedule->end_recurring_dt : '',
|
||||||
|
'end_recurring_hr' => $schedule->recurring ? $schedule->end_recurring_hr : '',
|
||||||
|
'recurring' => $schedule->recurring ? __('Yes') : __('No'),
|
||||||
|
'recurring_day' => $schedule->recurring ? implode(',', $schedule->recurring_day) : '',
|
||||||
|
'status' => $schedule->status,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @param Request $request
|
||||||
|
// * @param Builder $query
|
||||||
|
// * @return Builder
|
||||||
|
// */
|
||||||
|
// protected function sort($request, $query)
|
||||||
|
// {
|
||||||
|
// $columns = $this->sortFields($request);
|
||||||
|
// $sort = $request->get('sort', $this->default_sort);
|
||||||
|
//
|
||||||
|
// foreach ($sort as $column => $direction) {
|
||||||
|
// if (isset($columns[$column])) {
|
||||||
|
// $query->orderBy($columns[$column], $direction == 'desc' ? 'desc' : 'asc');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return $query;
|
||||||
|
// }
|
||||||
|
}
|
@@ -32,7 +32,17 @@ use Illuminate\Http\Request;
|
|||||||
|
|
||||||
abstract class TableController extends PaginatedAjaxController
|
abstract class TableController extends PaginatedAjaxController
|
||||||
{
|
{
|
||||||
protected $default_sort = [];
|
protected $model;
|
||||||
|
|
||||||
|
protected function sortFields($request)
|
||||||
|
{
|
||||||
|
if (isset($this->model)) {
|
||||||
|
$fields = \Schema::getColumnListing((new $this->model)->getTable());
|
||||||
|
return array_combine($fields, $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
final protected function baseRules()
|
final protected function baseRules()
|
||||||
{
|
{
|
||||||
|
@@ -25,48 +25,187 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Carbon\CarbonImmutable;
|
||||||
|
use Date;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class AlertSchedule extends Model
|
class AlertSchedule extends Model
|
||||||
{
|
{
|
||||||
|
const SCHEDULE_SET = 0;
|
||||||
|
const SCHEDULE_ACTIVE = 2;
|
||||||
|
const SCHEDULE_LAPSED = 1;
|
||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
protected $table = 'alert_schedule';
|
protected $table = 'alert_schedule';
|
||||||
protected $primaryKey = 'schedule_id';
|
protected $primaryKey = 'schedule_id';
|
||||||
|
protected $appends = ['start_recurring_dt', 'end_recurring_dt', 'start_recurring_hr', 'end_recurring_hr', 'status'];
|
||||||
|
|
||||||
|
private $timezone;
|
||||||
|
private $days = [
|
||||||
|
'Mo' => 1,
|
||||||
|
'Tu' => 2,
|
||||||
|
'We' => 3,
|
||||||
|
'Th' => 4,
|
||||||
|
'Fr' => 5,
|
||||||
|
'Sa' => 6,
|
||||||
|
'Su' => 7,
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(array $attributes = [])
|
||||||
|
{
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->timezone = config('app.timezone');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Accessors/Mutators ----
|
||||||
|
|
||||||
|
public function getRecurringDayAttribute()
|
||||||
|
{
|
||||||
|
return explode(',', str_replace(array_values($this->days), array_keys($this->days), $this->attributes['recurring_day']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRecurringDayAttribute($days)
|
||||||
|
{
|
||||||
|
$days = is_array($days) ? $days : explode(',', $days);
|
||||||
|
$new_days = [];
|
||||||
|
|
||||||
|
foreach ($days as $day) {
|
||||||
|
if (isset($this->days[$day])) {
|
||||||
|
$new_days[] = $this->days[$day];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->attributes['recurring_day'] = implode(',', $new_days);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStartAttribute()
|
||||||
|
{
|
||||||
|
return Date::parse($this->attributes['start'], 'UTC')->tz($this->timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartAttribute($start)
|
||||||
|
{
|
||||||
|
$this->attributes['start'] = $this->fromDateTime(Date::parse($start)->tz('UTC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndAttribute()
|
||||||
|
{
|
||||||
|
return Date::parse($this->attributes['end'], 'UTC')->tz($this->timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEndAttribute($end)
|
||||||
|
{
|
||||||
|
$this->attributes['end'] = $this->fromDateTime(Date::parse($end)->tz('UTC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStartRecurringDtAttribute()
|
||||||
|
{
|
||||||
|
return $this->start->toDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStartRecurringHrAttribute()
|
||||||
|
{
|
||||||
|
return $this->start->toTimeString('minute');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndRecurringDtAttribute()
|
||||||
|
{
|
||||||
|
$end = $this->end;
|
||||||
|
return $end->year == '9000' ? null : $end->toDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndRecurringHrAttribute()
|
||||||
|
{
|
||||||
|
return $this->end->toTimeString('minute');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartRecurringDtAttribute($date)
|
||||||
|
{
|
||||||
|
$this->start = $this->start->setDateFrom(Date::parse($date, $this->timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartRecurringHrAttribute($time)
|
||||||
|
{
|
||||||
|
$this->start = $this->start->setTimeFrom(Date::parse($time, $this->timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEndRecurringDtAttribute($date)
|
||||||
|
{
|
||||||
|
$this->end = $this->end->setDateFrom(Date::parse($date ?: '9000-09-09', $this->timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEndRecurringHrAttribute($time)
|
||||||
|
{
|
||||||
|
$this->end = $this->end->setTimeFrom(Date::parse($time, $this->timezone));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int Status 0: SCHEDULE_SET, 1: SCHEDULE_LAPSED, 2: SCHEDULE_ACTIVE
|
||||||
|
*/
|
||||||
|
public function getStatusAttribute()
|
||||||
|
{
|
||||||
|
$now = Carbon::now();
|
||||||
|
|
||||||
|
if ($now > $this->end) {
|
||||||
|
return self::SCHEDULE_LAPSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->recurring) {
|
||||||
|
return $now > $this->start ? self::SCHEDULE_ACTIVE : self::SCHEDULE_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurring
|
||||||
|
$now_time = $now->secondsSinceMidnight();
|
||||||
|
$start_time = $this->start->secondsSinceMidnight();
|
||||||
|
$end_time = $this->end->secondsSinceMidnight();
|
||||||
|
$after_start = $now > $this->start;
|
||||||
|
$spans_days = $start_time > $end_time;
|
||||||
|
|
||||||
|
// check inside start and end times or outside start and end times (if we span a day)
|
||||||
|
$active = $spans_days ? ($after_start && ($now_time < $end_time || $now_time >= $start_time)) : ($now_time >= $start_time && $now_time < $end_time);
|
||||||
|
|
||||||
|
return $active && Str::contains($this->attributes['recurring_day'], $now->format('N')) ? self::SCHEDULE_ACTIVE : self::SCHEDULE_SET;
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Query scopes ----
|
// ---- Query scopes ----
|
||||||
|
|
||||||
public function scopeIsActive($query)
|
public function scopeIsActive($query)
|
||||||
{
|
{
|
||||||
// TODO use Carbon?
|
|
||||||
return $query->where(function ($query) {
|
return $query->where(function ($query) {
|
||||||
$query->where(function ($query) {
|
$now = CarbonImmutable::now('UTC');
|
||||||
// Non recurring simply between start and end
|
$query->where('start', '<=', $now)
|
||||||
$query->where('recurring', 0)
|
->where('end', '>=', $now)
|
||||||
->where('start', '<=', DB::raw('NOW()'))
|
->where(function ($query) use ($now) {
|
||||||
->where('end', '>=', DB::raw('NOW()'));
|
$query->where('recurring', 0) // Non recurring simply between start and end
|
||||||
})->orWhere(function ($query) {
|
->orWhere(function ($query) use ($now) {
|
||||||
$query->where('recurring', 1)
|
$query->where('recurring', 1)
|
||||||
// Check the time is after the start date and before the end date, or end date is not set
|
// Check the time is after the start date and before the end date, or end date is not set
|
||||||
->where(function ($query) {
|
->where(function ($query) use ($now) {
|
||||||
$query->where('start_recurring_dt', '<=', DB::raw("date_format(NOW(), '%Y-%m-%d')"))
|
$query->where(function ($query) use ($now) {
|
||||||
->where(function ($query) {
|
// normal, inside one day
|
||||||
$query->where('end_recurring_dt', '>=', DB::raw("date_format(NOW(), '%Y-%m-%d')"))
|
$query->whereTime('start', '<', DB::raw("time(`end`)"))
|
||||||
->orWhereNull('end_recurring_dt');
|
->whereTime('start', '<=', $now->toTimeString())
|
||||||
|
->whereTime('end', '>', $now->toTimeString());
|
||||||
|
})->orWhere(function ($query) use ($now) {
|
||||||
|
// outside, spans days
|
||||||
|
$query->whereTime('start', '>', DB::raw("time(`end`)"))
|
||||||
|
->where(function ($query) use ($now) {
|
||||||
|
$query->whereTime('end', '<=', $now->toTimeString())
|
||||||
|
->orWhereTime('start', '>', $now->toTimeString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
// Check we are on the correct day of the week
|
||||||
|
->where(function ($query) use ($now) {
|
||||||
|
$query->where('recurring_day', 'like', $now->format('%N%'))
|
||||||
|
->orWhereNull('recurring_day');
|
||||||
});
|
});
|
||||||
})
|
|
||||||
// Check the time is between the start and end hour/minutes/seconds
|
|
||||||
->where('start_recurring_hr', '<=', DB::raw("date_format(NOW(), '%H:%i:%s')"))
|
|
||||||
->where('end_recurring_hr', '>=', DB::raw("date_format(NOW(), '%H:%i:%s')"))
|
|
||||||
// Check we are on the correct day of the week
|
|
||||||
->where(function ($query) {
|
|
||||||
/** @var Builder $query */
|
|
||||||
$query->where('recurring_day', 'like', DB::raw("CONCAT('%', date_format(NOW(), '%w'), '%')"))
|
|
||||||
->orWhereNull('recurring_day')
|
|
||||||
->orWhere('recurring_day', '');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +213,16 @@ class AlertSchedule extends Model
|
|||||||
|
|
||||||
public function devices()
|
public function devices()
|
||||||
{
|
{
|
||||||
return $this->morphedByMany(\App\Models\Device::class, 'alert_schedulable', 'alert_schedulables', 'schedule_id', 'schedule_id');
|
return $this->morphedByMany(\App\Models\Device::class, 'alert_schedulable', 'alert_schedulables', 'schedule_id', 'alert_schedulable_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deviceGroups()
|
public function deviceGroups()
|
||||||
{
|
{
|
||||||
return $this->morphedByMany(\App\Models\DeviceGroup::class, 'alert_schedulable');
|
return $this->morphedByMany(\App\Models\DeviceGroup::class, 'alert_schedulable', 'alert_schedulables', 'schedule_id', 'alert_schedulable_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function locations()
|
||||||
|
{
|
||||||
|
return $this->morphedByMany(\App\Models\Location::class, 'alert_schedulable', 'alert_schedulables', 'schedule_id', 'alert_schedulable_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -133,25 +133,25 @@ class Device extends BaseModel
|
|||||||
|
|
||||||
public function isUnderMaintenance()
|
public function isUnderMaintenance()
|
||||||
{
|
{
|
||||||
|
if (!$this->device_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$query = AlertSchedule::isActive()
|
$query = AlertSchedule::isActive()
|
||||||
->join('alert_schedulables', 'alert_schedule.schedule_id', 'alert_schedulables.schedule_id')
|
->where(function (Builder $query) {
|
||||||
->where(function ($query) {
|
$query->whereHas('devices', function (Builder $query) {
|
||||||
$query->where(function ($query) {
|
$query->where('alert_schedulables.alert_schedulable_id', $this->device_id);
|
||||||
$query->where('alert_schedulable_type', 'device')
|
|
||||||
->where('alert_schedulable_id', $this->device_id);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if ($this->groups) {
|
if ($this->groups) {
|
||||||
$query->orWhere(function ($query) {
|
$query->orWhereHas('deviceGroups', function (Builder $query) {
|
||||||
$query->where('alert_schedulable_type', 'device_group')
|
$query->whereIn('alert_schedulables.alert_schedulable_id', $this->groups->pluck('id'));
|
||||||
->whereIn('alert_schedulable_id', $this->groups->pluck('id'));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->location) {
|
if ($this->location) {
|
||||||
$query->orWhere(function ($query) {
|
$query->orWhereHas('locations', function (Builder $query) {
|
||||||
$query->where('alert_schedulable_type', 'location')
|
$query->where('alert_schedulables.alert_schedulable_id', $this->location->id);
|
||||||
->where('alert_schedulable_id', $this->location->id);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -85,6 +85,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
'sensor' => \App\Models\Sensor::class,
|
'sensor' => \App\Models\Sensor::class,
|
||||||
'device' => \App\Models\Device::class,
|
'device' => \App\Models\Device::class,
|
||||||
'device_group' => \App\Models\DeviceGroup::class,
|
'device_group' => \App\Models\DeviceGroup::class,
|
||||||
|
'location' => \App\Models\Location::class,
|
||||||
], $sensor_types));
|
], $sensor_types));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -212,6 +212,7 @@ return [
|
|||||||
'Config' => Illuminate\Support\Facades\Config::class,
|
'Config' => Illuminate\Support\Facades\Config::class,
|
||||||
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
'Cookie' => Illuminate\Support\Facades\Cookie::class,
|
||||||
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
'Crypt' => Illuminate\Support\Facades\Crypt::class,
|
||||||
|
'Date' => Illuminate\Support\Facades\Date::class,
|
||||||
'DB' => Illuminate\Support\Facades\DB::class,
|
'DB' => Illuminate\Support\Facades\DB::class,
|
||||||
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
|
||||||
'Event' => Illuminate\Support\Facades\Event::class,
|
'Event' => Illuminate\Support\Facades\Event::class,
|
||||||
|
54
database/migrations/2020_04_08_172357_alert_schedule_utc.php
Normal file
54
database/migrations/2020_04_08_172357_alert_schedule_utc.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
|
||||||
|
class AlertScheduleUtc extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (\LibreNMS\DB\Eloquent::getDriver() == 'mysql') {
|
||||||
|
DB::table('alert_schedule')->update([
|
||||||
|
'start' => DB::raw("CONVERT_TZ(IF(`recurring` = 1, STR_TO_DATE(CONCAT(start_recurring_dt, ' ', start_recurring_hr), '%Y-%m-%d %H:%i:%s'), start), @@global.time_zone, '+00:00')"),
|
||||||
|
'end' => DB::raw("CONVERT_TZ(IF(`recurring` = 1, STR_TO_DATE(CONCAT(IFNULL(end_recurring_dt, '9000-09-09'), ' ', end_recurring_hr), '%Y-%m-%d %H:%i:%s'), end), @@global.time_zone, '+00:00')"),
|
||||||
|
'recurring_day' => DB::raw('REPLACE(recurring_day, 0, 7)'), // convert to RFC N date format
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::table('alert_schedule', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['start_recurring_dt', 'start_recurring_hr', 'end_recurring_dt', 'end_recurring_hr']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('alert_schedule', function (Blueprint $table) {
|
||||||
|
$table->date('start_recurring_dt')->nullable(false)->default('1970-01-01')->after('end');
|
||||||
|
$table->time('start_recurring_hr')->nullable(false)->default('00:00:00')->after('start_recurring_dt');
|
||||||
|
$table->date('end_recurring_dt')->nullable()->after('start_recurring_hr');
|
||||||
|
$table->time('end_recurring_hr')->nullable(false)->default('00:00:00')->after('end_recurring_dt');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (\LibreNMS\DB\Eloquent::getDriver() == 'mysql') {
|
||||||
|
DB::table('alert_schedule')->update([
|
||||||
|
'start' => DB::raw("CONVERT_TZ(start, '+00:00', @@global.time_zone)"),
|
||||||
|
'end' => DB::raw("CONVERT_TZ(end, '+00:00', @@global.time_zone)"),
|
||||||
|
'start_recurring_dt' => DB::raw("DATE(CONVERT_TZ(start, '+00:00', @@global.time_zone))"),
|
||||||
|
'start_recurring_hr' => DB::raw("TIME(CONVERT_TZ(start, '+00:00', @@global.time_zone))"),
|
||||||
|
'end_recurring_dt' => DB::raw("DATE(CONVERT_TZ(end, '+00:00', @@global.time_zone))"),
|
||||||
|
'end_recurring_hr' => DB::raw("TIME(CONVERT_TZ(end, '+00:00', @@global.time_zone))"),
|
||||||
|
'recurring_day' => DB::raw('REPLACE(recurring_day, 7, 0)'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -14,6 +14,8 @@ use Illuminate\Support\Str;
|
|||||||
* the source code distribution for details.
|
* the source code distribution for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
if (!Auth::user()->hasGlobalAdmin()) {
|
if (!Auth::user()->hasGlobalAdmin()) {
|
||||||
header('Content-type: text/plain');
|
header('Content-type: text/plain');
|
||||||
die('ERROR: You need to be admin');
|
die('ERROR: You need to be admin');
|
||||||
@@ -34,7 +36,7 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
|
|
||||||
$title = mres($_POST['title']);
|
$title = mres($_POST['title']);
|
||||||
$notes = mres($_POST['notes']);
|
$notes = mres($_POST['notes']);
|
||||||
$recurring = mres($_POST['recurring']);
|
$recurring = $_POST['recurring'] ? 1 : 0;
|
||||||
$start_recurring_dt = mres($_POST['start_recurring_dt']);
|
$start_recurring_dt = mres($_POST['start_recurring_dt']);
|
||||||
$end_recurring_dt = mres($_POST['end_recurring_dt']);
|
$end_recurring_dt = mres($_POST['end_recurring_dt']);
|
||||||
$start_recurring_hr = mres($_POST['start_recurring_hr']);
|
$start_recurring_hr = mres($_POST['start_recurring_hr']);
|
||||||
@@ -75,7 +77,7 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
$message .= 'Please check end recurring date<br />';
|
$message .= 'Please check end recurring date<br />';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$end_recurring_dt = null;
|
$end_recurring_dt = '9000-09-09';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($start_recurring_hr)) {
|
if (empty($start_recurring_hr)) {
|
||||||
@@ -117,18 +119,27 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty($message)) {
|
if (empty($message)) {
|
||||||
if (empty($schedule_id)) {
|
$alert_schedule = \App\Models\AlertSchedule::findOrNew($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');
|
$alert_schedule->title = $title;
|
||||||
} else {
|
$alert_schedule->notes = $notes;
|
||||||
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->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();
|
$items = array();
|
||||||
$fail = 0;
|
$fail = 0;
|
||||||
|
|
||||||
if ($update == 1) {
|
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) {
|
foreach ($_POST['maps'] as $target) {
|
||||||
@@ -141,7 +152,7 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
$target = substr($target, 1);
|
$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)) {
|
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 = 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;
|
$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_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';
|
$message = 'Issue scheduling maintenance';
|
||||||
} else {
|
} else {
|
||||||
$status = 'ok';
|
$status = 'ok';
|
||||||
@@ -176,7 +187,7 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
);
|
);
|
||||||
} elseif ($sub_type == 'parse-maintenance') {
|
} elseif ($sub_type == 'parse-maintenance') {
|
||||||
$schedule_id = mres($_POST['schedule_id']);
|
$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 = [];
|
$items = [];
|
||||||
foreach (dbFetchRows('SELECT `alert_schedulable_type`, `alert_schedulable_id` FROM `alert_schedulables` WHERE `schedule_id`=?', [$schedule_id]) as $target) {
|
foreach (dbFetchRows('SELECT `alert_schedulable_type`, `alert_schedulable_id` FROM `alert_schedulables` WHERE `schedule_id`=?', [$schedule_id]) as $target) {
|
||||||
$id = $target['alert_schedulable_id'];
|
$id = $target['alert_schedulable_id'];
|
||||||
@@ -195,19 +206,9 @@ if ($sub_type == 'new-maintenance') {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = array(
|
$response = $alert_schedule->toArray();
|
||||||
'start' => $schedule['start'],
|
$response['recurring_day'] = $alert_schedule->getOriginal('recurring_day');
|
||||||
'end' => $schedule['end'],
|
$response['targets'] = $items;
|
||||||
'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,
|
|
||||||
);
|
|
||||||
} elseif ($sub_type == 'del-maintenance') {
|
} elseif ($sub_type == 'del-maintenance') {
|
||||||
$schedule_id = mres($_POST['del_schedule_id']);
|
$schedule_id = mres($_POST['del_schedule_id']);
|
||||||
dbDelete('alert_schedule', '`schedule_id`=?', array($schedule_id));
|
dbDelete('alert_schedule', '`schedule_id`=?', array($schedule_id));
|
||||||
|
@@ -93,13 +93,13 @@ if (\Auth::user()->hasGlobalAdmin()) {
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="recurring_day" class="col-sm-4 control-label">Only on weekday: </label>
|
<label for="recurring_day" class="col-sm-4 control-label">Only on weekday: </label>
|
||||||
<div class="col-sm-8">
|
<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;"><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" 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" 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" 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" 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" 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" 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;padding-left: 20px;"><label><input type="checkbox" style="width: 20px;" class="form-control" name="recurring_day[]" value="7" />Su</label></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -126,7 +126,6 @@ $('#schedule-maintenance').on('hide.bs.modal', function (event) {
|
|||||||
$('#schedule_id').val('');
|
$('#schedule_id').val('');
|
||||||
$('#title').val('');
|
$('#title').val('');
|
||||||
$('#notes').val('');
|
$('#notes').val('');
|
||||||
$('#recurring').val('');
|
|
||||||
$('#start').val(moment().format('YYYY-MM-DD HH:mm')).data("DateTimePicker").maxDate(false).minDate(moment());
|
$('#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());
|
$('#end').val(moment().add(1, 'hour').format('YYYY-MM-DD HH:mm')).data("DateTimePicker").maxDate(false).minDate(moment());
|
||||||
var $startRecurringDt = $('#start_recurring_dt');
|
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);
|
$('#start_recurring_hr').val('').data("DateTimePicker").minDate(false).maxDate(false);
|
||||||
$('#end_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").bootstrapSwitch('state', false);
|
||||||
$('#recurring').val(0);
|
$('#recurring').val(0);
|
||||||
$('#norecurringgroup').show();
|
$('#norecurringgroup').show();
|
||||||
@@ -184,7 +183,7 @@ $('#schedule-maintenance').on('show.bs.modal', function (event) {
|
|||||||
$('#end_recurring_dt').val('');
|
$('#end_recurring_dt').val('');
|
||||||
$('#start_recurring_hr').val('');
|
$('#start_recurring_hr').val('');
|
||||||
$('#end_recurring_hr').val('');
|
$('#end_recurring_hr').val('');
|
||||||
$('#recurring_day').prop('checked', false);
|
$("input[name='recurring_day[]']").prop('checked', false);
|
||||||
$("#recurring").bootstrapSwitch('state', false);
|
$("#recurring").bootstrapSwitch('state', false);
|
||||||
$('#recurring').val(0);
|
$('#recurring').val(0);
|
||||||
}else{
|
}else{
|
||||||
@@ -211,7 +210,7 @@ $('#schedule-maintenance').on('show.bs.modal', function (event) {
|
|||||||
$("input[name='recurring_day[]'][value="+checkedday+"]").prop('checked', true);
|
$("input[name='recurring_day[]'][value="+checkedday+"]").prop('checked', true);
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
$('#recurring_day').prop('checked', false);
|
$("input[name='recurring_day[]']").prop('checked', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#norecurringgroup').hide();
|
$('#norecurringgroup').hide();
|
||||||
|
@@ -31,8 +31,8 @@ if (Auth::user()->hasGlobalAdmin()) {
|
|||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
<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>
|
<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="del_schedule_id" id="del_schedule_id">
|
||||||
<input type="hidden" name="type" id="type" value="schedule-maintenance">
|
<input type="hidden" name="type" value="schedule-maintenance">
|
||||||
<input type="hidden" name="sub_type" id="sub_type" value="del-maintenance">
|
<input type="hidden" name="sub_type" value="del-maintenance">
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</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>"
|
"<div class=\"col-sm-4 actionBar\"><p class=\"{{css.search}}\"></p><p class=\"{{css.actions}}\"></p></div></div></div>"
|
||||||
},
|
},
|
||||||
rowCount: [50, 100, 250, -1],
|
rowCount: [50, 100, 250, -1],
|
||||||
post: function () {
|
url: "ajax/table/alert-schedule"
|
||||||
return {
|
|
||||||
id: "alert-schedule",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
url: "ajax_table.php"
|
|
||||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||||
/* Executes after data is loaded and rendered */
|
/* Executes after data is loaded and rendered */
|
||||||
grid.find(".command-edit").on("click", function(e) {
|
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>
|
<script>
|
||||||
$('[type="checkbox"]').bootstrapSwitch('offColor', 'danger');
|
$('[type="checkbox"]').bootstrapSwitch('offColor', 'danger');
|
||||||
|
|
||||||
$("#maintenance").click(function() {
|
$("#maintenance").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
var device_id = $(this).data("device_id");
|
var device_id = $(this).data("device_id");
|
||||||
var title = '<?=display($device['hostname']);?>';
|
var title = '<?=display($device['hostname']);?>';
|
||||||
var notes = '';
|
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);
|
|
@@ -103,10 +103,6 @@ alert_schedule:
|
|||||||
- { Field: recurring, Type: 'tinyint unsigned', 'Null': false, Extra: '', Default: '0' }
|
- { Field: recurring, Type: 'tinyint unsigned', 'Null': false, Extra: '', Default: '0' }
|
||||||
- { Field: start, Type: datetime, 'Null': false, Extra: '', Default: '1970-01-02 00:00:01' }
|
- { Field: start, Type: datetime, 'Null': false, Extra: '', Default: '1970-01-02 00:00:01' }
|
||||||
- { Field: end, Type: datetime, 'Null': false, Extra: '', Default: '1970-01-02 00:00:01' }
|
- { Field: end, Type: datetime, 'Null': false, Extra: '', Default: '1970-01-02 00:00:01' }
|
||||||
- { Field: start_recurring_dt, Type: date, 'Null': false, Extra: '', Default: '1970-01-01' }
|
|
||||||
- { Field: end_recurring_dt, Type: date, 'Null': true, Extra: '' }
|
|
||||||
- { Field: start_recurring_hr, Type: time, 'Null': false, Extra: '', Default: '00:00:00' }
|
|
||||||
- { Field: end_recurring_hr, Type: time, 'Null': false, Extra: '', Default: '00:00:00' }
|
|
||||||
- { Field: recurring_day, Type: varchar(15), 'Null': true, Extra: '' }
|
- { Field: recurring_day, Type: varchar(15), 'Null': true, Extra: '' }
|
||||||
- { Field: title, Type: varchar(255), 'Null': false, Extra: '' }
|
- { Field: title, Type: varchar(255), 'Null': false, Extra: '' }
|
||||||
- { Field: notes, Type: text, 'Null': false, Extra: '' }
|
- { Field: notes, Type: text, 'Null': false, Extra: '' }
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
@if($parent_id)
|
@if($parent_id)
|
||||||
<a href="{{ route('device', $parent_id) }}" title="@lang('VM Host')"><i class="fa fa-server fa-fw fa-lg"></i></a>
|
<a href="{{ route('device', $parent_id) }}" title="@lang('VM Host')"><i class="fa fa-server fa-fw fa-lg"></i></a>
|
||||||
@endif
|
@endif
|
||||||
@if(\LibreNMS\Alert\AlertUtil::isMaintenance($device_id))
|
@if($device->isUnderMaintenance())
|
||||||
<span title="@lang('Scheduled Maintenance')" class="fa fa-wrench fa-fw fa-lg"></span>
|
<span title="@lang('Scheduled Maintenance')" class="fa fa-wrench fa-fw fa-lg"></span>
|
||||||
@endif
|
@endif
|
||||||
<span style="font-size: 20px;">@deviceLink($device)</span><br/>
|
<span style="font-size: 20px;">@deviceLink($device)</span><br/>
|
||||||
|
@@ -108,6 +108,7 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
|
|||||||
|
|
||||||
// jquery bootgrid data controllers
|
// jquery bootgrid data controllers
|
||||||
Route::group(['prefix' => 'table', 'namespace' => 'Table'], function () {
|
Route::group(['prefix' => 'table', 'namespace' => 'Table'], function () {
|
||||||
|
Route::post('alert-schedule', 'AlertScheduleController');
|
||||||
Route::post('customers', 'CustomersController');
|
Route::post('customers', 'CustomersController');
|
||||||
Route::post('device', 'DeviceController');
|
Route::post('device', 'DeviceController');
|
||||||
Route::post('eventlog', 'EventlogController');
|
Route::post('eventlog', 'EventlogController');
|
||||||
|
Reference in New Issue
Block a user