session->get('active_workspace_id'); $alerts = (new AlertModel())->forWorkspace($workspaceId); $recent = (new AlertHistoryModel())->recentForWorkspace($workspaceId, 12); return view('alert/index', [ 'title' => 'Alerts | Chart-Board', 'alerts' => $alerts, 'recent' => $recent, ]); } public function create() { $workspaceId = (int) $this->session->get('active_workspace_id'); $charts = (new ChartModel())->forWorkspace($workspaceId); return view('alert/create', [ 'title' => 'New alert | Chart-Board', 'charts' => $charts, ]); } public function store() { $workspaceId = (int) $this->session->get('active_workspace_id'); $userId = (int) $this->session->get('user_id'); $rules = [ 'name' => 'required|min_length[2]|max_length[200]', 'chart_id' => 'required|integer', 'metric_field' => 'required|max_length[150]', 'condition' => 'required|in_list[gt,lt,eq,gte,lte]', 'threshold' => 'required|decimal', 'check_interval' => 'permit_empty|integer', 'notify_email' => 'permit_empty|in_list[0,1]', 'notify_slack' => 'permit_empty|in_list[0,1]', 'email_addresses' => 'permit_empty|max_length[2000]', 'slack_webhook' => 'permit_empty|max_length[500]', ]; if (! $this->validate($rules)) { return redirect()->back()->withInput()->with('errors', $this->validator->getErrors()); } $chartId = (int) $this->request->getPost('chart_id'); $chart = (new ChartModel())->where('workspace_id', $workspaceId)->find($chartId); if (! $chart) { return redirect()->back()->withInput()->with('error', 'Chart not found.'); } $notifyEmail = (int) $this->request->getPost('notify_email') === 1 ? 1 : 0; $notifySlack = (int) $this->request->getPost('notify_slack') === 1 ? 1 : 0; (new AlertModel())->insert([ 'workspace_id' => $workspaceId, 'chart_id' => $chartId, 'name' => strip_tags((string) $this->request->getPost('name')), 'metric_field' => trim((string) $this->request->getPost('metric_field')), 'condition' => (string) $this->request->getPost('condition'), 'threshold' => (float) $this->request->getPost('threshold'), 'check_interval' => max(1, (int) ($this->request->getPost('check_interval') ?: 15)), 'notify_email' => $notifyEmail, 'email_addresses' => trim((string) $this->request->getPost('email_addresses')) ?: null, 'notify_slack' => $notifySlack, 'slack_webhook' => trim((string) $this->request->getPost('slack_webhook')) ?: null, 'is_active' => 1, 'is_muted_until' => null, 'created_by' => $userId, ]); return redirect()->to('/alert')->with('success', 'Alert created.'); } public function edit(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $charts = (new ChartModel())->forWorkspace($workspaceId); return view('alert/edit', [ 'title' => 'Edit alert | Chart-Board', 'alert' => $alert, 'charts' => $charts, ]); } public function update(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $rules = [ 'name' => 'required|min_length[2]|max_length[200]', 'chart_id' => 'required|integer', 'metric_field' => 'required|max_length[150]', 'condition' => 'required|in_list[gt,lt,eq,gte,lte]', 'threshold' => 'required|decimal', 'check_interval' => 'permit_empty|integer', 'notify_email' => 'permit_empty|in_list[0,1]', 'notify_slack' => 'permit_empty|in_list[0,1]', 'email_addresses' => 'permit_empty|max_length[2000]', 'slack_webhook' => 'permit_empty|max_length[500]', 'is_active' => 'permit_empty|in_list[0,1]', ]; if (! $this->validate($rules)) { return redirect()->back()->withInput()->with('errors', $this->validator->getErrors()); } $chartId = (int) $this->request->getPost('chart_id'); $chart = (new ChartModel())->where('workspace_id', $workspaceId)->find($chartId); if (! $chart) { return redirect()->back()->withInput()->with('error', 'Chart not found.'); } $notifyEmail = (int) $this->request->getPost('notify_email') === 1 ? 1 : 0; $notifySlack = (int) $this->request->getPost('notify_slack') === 1 ? 1 : 0; $isActive = (int) $this->request->getPost('is_active') === 1 ? 1 : 0; $model->update($id, [ 'chart_id' => $chartId, 'name' => strip_tags((string) $this->request->getPost('name')), 'metric_field' => trim((string) $this->request->getPost('metric_field')), 'condition' => (string) $this->request->getPost('condition'), 'threshold' => (float) $this->request->getPost('threshold'), 'check_interval' => max(1, (int) ($this->request->getPost('check_interval') ?: 15)), 'notify_email' => $notifyEmail, 'email_addresses' => trim((string) $this->request->getPost('email_addresses')) ?: null, 'notify_slack' => $notifySlack, 'slack_webhook' => trim((string) $this->request->getPost('slack_webhook')) ?: null, 'is_active' => $isActive, ]); return redirect()->back()->with('success', 'Alert updated.'); } public function delete(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $model->delete($id); return redirect()->to('/alert')->with('success', 'Alert deleted.'); } public function mute(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $hours = (int) $this->request->getPost('hours'); if (! in_array($hours, [1, 4, 24], true)) { $hours = 1; } $until = date('Y-m-d H:i:s', time() + $hours * 3600); $model->update($id, ['is_muted_until' => $until]); return redirect()->back()->with('success', 'Alert muted for ' . $hours . ' hour(s).'); } public function unmute(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $model->update($id, ['is_muted_until' => null]); return redirect()->back()->with('success', 'Mute cleared.'); } public function history(int $id) { $workspaceId = (int) $this->session->get('active_workspace_id'); $model = new AlertModel(); $alert = $model->where('workspace_id', $workspaceId)->find($id); if (! $alert) { return redirect()->to('/alert')->with('error', 'Alert not found.'); } $page = max(1, (int) $this->request->getGet('page')); $perPage = 25; $offset = ($page - 1) * $perPage; $histModel = new AlertHistoryModel(); $rows = $histModel->forAlert($id, $perPage, $offset); $total = $histModel->countForAlert($id); return view('alert/history', [ 'title' => 'Alert history | Chart-Board', 'alert' => $alert, 'history' => $rows, 'page' => $page, 'perPage' => $perPage, 'total' => $total, ]); } }