Commit 5dbb2845 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '213877' into 'master'

Add initial empty state for surface alerts

See merge request gitlab-org/gitlab!29775
parents d60e8d68 d6aa6f33
<script>
import { GlEmptyState, GlButton, GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
GlEmptyState,
GlButton,
GlLoadingIcon,
},
props: {
indexPath: {
type: String,
required: true,
},
enableAlertManagementPath: {
type: String,
required: true,
},
emptyAlertSvgPath: {
type: String,
required: true,
},
},
data() {
return {
alerts: [],
loading: false,
};
},
};
</script>
<template>
<div>
<div v-if="alerts.length > 0" class="alert-management-list">
<div v-if="loading" class="py-3">
<gl-loading-icon size="md" />
</div>
</div>
<template v-else>
<gl-empty-state :title="__('Surface alerts in GitLab')" :svg-path="emptyAlertSvgPath">
<template #description>
<div class="d-block">
<span>{{
__(
'Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents.',
)
}}</span>
<a href="/help/user/project/operations/alert_management.html">
{{ __('More information') }}
</a>
</div>
<div class="d-block center pt-4">
<gl-button category="primary" variant="success" :href="enableAlertManagementPath">{{
__('Authorize external service')
}}</gl-button>
</div>
</template>
</gl-empty-state>
</template>
</div>
</template>
import Vue from 'vue';
import AlertManagementList from './components/alert_management_list.vue';
export default () => {
const selector = '#js-alert_management';
const domEl = document.querySelector(selector);
const { indexPath, enableAlertManagementPath, emptyAlertSvgPath } = domEl.dataset;
return new Vue({
el: selector,
components: {
AlertManagementList,
},
render(createElement) {
return createElement('alert-management-list', {
props: {
indexPath,
enableAlertManagementPath,
emptyAlertSvgPath,
},
});
},
});
};
import axios from '~/lib/utils/axios_utils';
export default {
getAlertManagementList({ endpoint }) {
return axios.get(endpoint);
},
};
import AlertManagementList from '~/alert_management/list';
document.addEventListener('DOMContentLoaded', () => {
AlertManagementList();
});
# frozen_string_literal: true
class Projects::AlertManagementController < Projects::ApplicationController
def index
respond_to do |format|
format.html
end
end
end
# frozen_string_literal: true
module Projects::AlertManagementHelper
def alert_management_data(project)
{
'index-path' => project_alert_management_index_path(project,
format: :json),
'enable-alert-management-path' => project_settings_operations_path(project),
'empty-alert-svg-path' => image_path('illustrations/alert-management-empty-state.svg')
}
end
end
...@@ -448,6 +448,7 @@ module ProjectsHelper ...@@ -448,6 +448,7 @@ module ProjectsHelper
clusters: :read_cluster, clusters: :read_cluster,
serverless: :read_cluster, serverless: :read_cluster,
error_tracking: :read_sentry_issue, error_tracking: :read_sentry_issue,
alert_management: :read_alert_management,
labels: :read_label, labels: :read_label,
issues: :read_issue, issues: :read_issue,
project_members: :read_project_member, project_members: :read_project_member,
...@@ -707,6 +708,7 @@ module ProjectsHelper ...@@ -707,6 +708,7 @@ module ProjectsHelper
clusters clusters
functions functions
error_tracking error_tracking
alert_management
user user
gcp gcp
logs logs
......
...@@ -223,6 +223,7 @@ class ProjectPolicy < BasePolicy ...@@ -223,6 +223,7 @@ class ProjectPolicy < BasePolicy
enable :read_merge_request enable :read_merge_request
enable :read_sentry_issue enable :read_sentry_issue
enable :update_sentry_issue enable :update_sentry_issue
enable :read_alert_management
enable :read_prometheus enable :read_prometheus
enable :read_metrics_dashboard_annotation enable :read_metrics_dashboard_annotation
end end
......
...@@ -222,6 +222,12 @@ ...@@ -222,6 +222,12 @@
%span %span
= _('Metrics') = _('Metrics')
- if project_nav_tab?(:alert_management)
= nav_link(controller: :alert_management) do
= link_to project_alert_management_index_path(@project), title: _('Alerts'), class: 'shortcuts-tracking qa-operations-tracking-link' do
%span
= _('Alerts')
= render_if_exists "layouts/nav/sidebar/tracing_link" = render_if_exists "layouts/nav/sidebar/tracing_link"
= nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do = nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do
......
- page_title _('Alerts')
#js-alert_management{ data: alert_management_data(@project) }
---
title: Surface alerts add sidebar link
merge_request: 29775
author:
type: changed
---
title: Surface alerts add empty state
merge_request: 29775
author:
type: added
...@@ -277,6 +277,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -277,6 +277,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end end
end end
resources :alert_management, only: [:index], controller: :alert_management
namespace :error_tracking do namespace :error_tracking do
resources :projects, only: :index resources :projects, only: :index
end end
...@@ -503,7 +505,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -503,7 +505,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
:labels, :milestones, :services, :boards, :releases, :labels, :milestones, :services, :boards, :releases,
:forks, :group_links, :import, :avatar, :mirror, :forks, :group_links, :import, :avatar, :mirror,
:cycle_analytics, :mattermost, :variables, :triggers, :cycle_analytics, :mattermost, :variables, :triggers,
:environments, :protected_environments, :error_tracking, :environments, :protected_environments, :error_tracking, :alert_management,
:serverless, :clusters, :audit_events, :wikis, :merge_requests, :serverless, :clusters, :audit_events, :wikis, :merge_requests,
:vulnerability_feedback, :security, :dependencies) :vulnerability_feedback, :security, :dependencies)
end end
......
...@@ -2727,6 +2727,9 @@ msgstr "" ...@@ -2727,6 +2727,9 @@ msgstr ""
msgid "Authorize %{link_to_client} to use your account?" msgid "Authorize %{link_to_client} to use your account?"
msgstr "" msgstr ""
msgid "Authorize external service"
msgstr ""
msgid "Authorized %{new_chat_name}" msgid "Authorized %{new_chat_name}"
msgstr "" msgstr ""
...@@ -7340,6 +7343,9 @@ msgstr "" ...@@ -7340,6 +7343,9 @@ msgstr ""
msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}" msgid "Dismissed on pipeline %{pipelineLink} at %{projectLink}"
msgstr "" msgstr ""
msgid "Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
msgstr ""
msgid "Display name" msgid "Display name"
msgstr "" msgstr ""
...@@ -20033,6 +20039,9 @@ msgstr "" ...@@ -20033,6 +20039,9 @@ msgstr ""
msgid "Support page URL" msgid "Support page URL"
msgstr "" msgstr ""
msgid "Surface alerts in GitLab"
msgstr ""
msgid "Switch branch/tag" msgid "Switch branch/tag"
msgstr "" msgstr ""
......
import { mount } from '@vue/test-utils';
import { GlEmptyState } from '@gitlab/ui';
import stubChildren from 'helpers/stub_children';
import AlertManagementList from '~/alert_management/components/alert_management_list.vue';
describe('AlertManagementList', () => {
let wrapper;
function mountComponent({ stubs = {} } = {}) {
wrapper = mount(AlertManagementList, {
propsData: {
indexPath: '/path',
enableAlertManagementPath: '/link',
emptyAlertSvgPath: 'illustration/path',
},
stubs: {
...stubChildren(AlertManagementList),
...stubs,
},
});
}
afterEach(() => {
if (wrapper) {
wrapper.destroy();
}
});
describe('alert management feature renders empty state', () => {
beforeEach(() => {
mountComponent();
});
it('shows empty state', () => {
expect(wrapper.find(GlEmptyState).exists()).toBe(true);
});
});
});
# frozen_string_literal: true
require 'spec_helper'
describe Projects::AlertManagementHelper do
include Gitlab::Routing.url_helpers
let(:project) { create(:project) }
describe '#alert_management_data' do
let(:setting_path) { project_settings_operations_path(project) }
let(:index_path) do
project_alert_management_index_path(project, format: :json)
end
context 'without alert_managements_setting' do
it 'returns frontend configuration' do
expect(alert_management_data(project)).to eq(
'index-path' => index_path,
'enable-alert-management-path' => setting_path,
"empty-alert-svg-path" => "/images/illustrations/alert-management-empty-state.svg"
)
end
end
end
end
...@@ -62,6 +62,7 @@ RSpec.shared_context 'project navbar structure' do ...@@ -62,6 +62,7 @@ RSpec.shared_context 'project navbar structure' do
nav_item: _('Operations'), nav_item: _('Operations'),
nav_sub_items: [ nav_sub_items: [
_('Metrics'), _('Metrics'),
_('Alerts'),
_('Environments'), _('Environments'),
_('Error Tracking'), _('Error Tracking'),
_('Serverless'), _('Serverless'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment