Commit a4d48592 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch '213892-Alerts-empty-state' into 'master'

Empty state for alerts list

See merge request gitlab-org/gitlab!30215
parents 8c1041ac 37f2fc45
<script>
import { GlEmptyState, GlButton, GlLoadingIcon } from '@gitlab/ui';
import { mapState } from 'vuex';
import { GlEmptyState, GlButton, GlLoadingIcon, GlTable, GlAlert } from '@gitlab/ui';
import { __ } from '~/locale';
const tdClass = 'table-col d-flex';
export default {
fields: [
{
key: 'severity',
label: __('Severity'),
tdClass,
},
{
key: 'start_time',
label: __('Start Time'),
tdClass,
},
{
key: 'end_time',
label: __('End Time'),
tdClass,
},
{
key: 'alert',
label: __('Alert'),
thClass: 'w-30p',
tdClass,
},
{
key: 'events',
label: __('Events'),
tdClass,
},
{
key: 'status',
label: __('Status'),
tdClass,
},
],
components: {
GlEmptyState,
GlButton,
GlLoadingIcon,
GlTable,
GlAlert,
},
props: {
indexPath: {
type: String,
required: true,
},
// TODO: Handle alertManagementEnabled depending on resolution - https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30024.
alertManagementEnabled: {
type: Boolean,
required: false,
default: true,
},
enableAlertManagementPath: {
type: String,
required: true,
......@@ -23,19 +68,45 @@ export default {
},
data() {
return {
alerts: [],
loading: false,
isAlertDismissed: false,
};
},
computed: {
...mapState('list', ['alerts', 'loading']),
showNoAlertsMsg() {
return !this.alerts.length && !this.isAlertDismissed;
},
},
};
</script>
<template>
<div>
<div v-if="alerts.length > 0" class="alert-management-list">
<div v-if="alertManagementEnabled" class="alert-management-list">
<gl-alert v-if="showNoAlertsMsg" @dismiss="isAlertDismissed = true">
{{
__(
`No alerts available to display. If you think you're seeing this message in error, refresh the page.`,
)
}}
</gl-alert>
<div v-if="loading" class="py-3">
<gl-loading-icon size="md" />
</div>
<gl-table
class="mt-3"
:items="alerts"
:fields="$options.fields"
:show-empty="true"
fixed
stacked="sm"
tbody-tr-class="table-row mb-4"
>
<template #empty>
{{ __('No alerts to display.') }}
</template>
</gl-table>
</div>
<template v-else>
<gl-empty-state :title="__('Surface alerts in GitLab')" :svg-path="emptyAlertSvgPath">
......@@ -51,9 +122,9 @@ export default {
</a>
</div>
<div class="d-block center pt-4">
<gl-button category="primary" variant="success" :href="enableAlertManagementPath">{{
__('Authorize external service')
}}</gl-button>
<gl-button category="primary" variant="success" :href="enableAlertManagementPath">
{{ __('Authorize external service') }}
</gl-button>
</div>
</template>
</gl-empty-state>
......
import Vue from 'vue';
import store from './store';
import AlertManagementList from './components/alert_management_list.vue';
export default () => {
......@@ -12,6 +13,7 @@ export default () => {
components: {
AlertManagementList,
},
store,
render(createElement) {
return createElement('alert-management-list', {
props: {
......
import Vue from 'vue';
import Vuex from 'vuex';
import * as listActions from './list/actions';
import listMutations from './list/mutations';
import listState from './list/state';
Vue.use(Vuex);
export const createStore = () =>
new Vuex.Store({
modules: {
list: {
namespaced: true,
state: listState(),
actions: listActions,
mutations: listMutations,
},
},
});
export default createStore();
import * as types from './mutation_types';
export const setAlerts = ({ commit }, alerts) => {
commit(types.SET_ALERTS, alerts);
};
export const setLoading = ({ commit }, loading) => {
commit(types.SET_LOADING, loading);
};
export const SET_ALERTS = 'SET_ALERTS';
export const SET_LOADING = 'SET_LOADING';
import * as types from './mutation_types';
export default {
[types.SET_ALERTS](state, alerts) {
state.alerts = alerts;
},
[types.SET_LOADING](state, loading) {
state.loading = loading;
},
};
export default () => ({
alerts: [],
loading: false,
});
// these styles need to be deleted once GlTable component looks in GitLab same as in @gitlab/ui
.alert-management-list {
table {
color: $gray-700;
tr {
td,
th {
@include gl-p-4;
}
th {
background-color: transparent;
font-weight: $gl-font-weight-bold;
color: $gl-gray-600;
@include gl-border-b-1;
@include gl-border-b-solid;
border-color: $gray-100;
}
td {
@include gl-border-0;
}
}
}
}
---
title: Empty state for alerts list
merge_request: 30215
author:
type: added
......@@ -7835,6 +7835,9 @@ msgstr ""
msgid "Encountered an error while rendering: %{err}"
msgstr ""
msgid "End Time"
msgstr ""
msgid "End date"
msgstr ""
......@@ -13661,6 +13664,12 @@ msgstr ""
msgid "No activities found"
msgstr ""
msgid "No alerts available to display. If you think you're seeing this message in error, refresh the page."
msgstr ""
msgid "No alerts to display."
msgstr ""
msgid "No application_settings found"
msgstr ""
......@@ -18768,6 +18777,9 @@ msgstr ""
msgid "Settings to prevent self-approval across all projects in the instance. Only an administrator can modify these settings."
msgstr ""
msgid "Severity"
msgstr ""
msgid "Severity: %{severity}"
msgstr ""
......@@ -19550,6 +19562,9 @@ msgstr ""
msgid "Start GitLab Ultimate trial"
msgstr ""
msgid "Start Time"
msgstr ""
msgid "Start Web Terminal"
msgstr ""
......
import { mount } from '@vue/test-utils';
import { GlEmptyState } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import { GlEmptyState, GlTable, GlAlert } from '@gitlab/ui';
import Vuex from 'vuex';
import stubChildren from 'helpers/stub_children';
import AlertManagementList from '~/alert_management/components/alert_management_list.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('AlertManagementList', () => {
let wrapper;
let store;
const findAlertsTable = () => wrapper.find(GlTable);
const findAlert = () => wrapper.find(GlAlert);
function mountComponent({ stubs = {} } = {}) {
function mountComponent({ stubs = {}, alertManagementEnabled = false } = {}) {
wrapper = mount(AlertManagementList, {
localVue,
store,
propsData: {
indexPath: '/path',
enableAlertManagementPath: '/link',
emptyAlertSvgPath: 'illustration/path',
alertManagementEnabled,
},
stubs: {
...stubChildren(AlertManagementList),
......@@ -20,19 +31,43 @@ describe('AlertManagementList', () => {
});
}
beforeEach(() => {
store = new Vuex.Store({
modules: {
list: {
namespaced: true,
},
},
});
mountComponent();
});
afterEach(() => {
if (wrapper) {
wrapper.destroy();
store = null;
}
});
describe('alert management feature renders empty state', () => {
beforeEach(() => {
mountComponent();
});
it('shows empty state', () => {
expect(wrapper.find(GlEmptyState).exists()).toBe(true);
});
});
describe('Alerts table', () => {
it('shows empty list', () => {
store.state.list = {
alerts: [],
loading: false,
};
mountComponent({ alertManagementEnabled: true });
return wrapper.vm.$nextTick().then(() => {
expect(findAlertsTable().exists()).toBe(true);
expect(findAlert().text()).toContain('No alerts available to display');
});
});
});
});
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