Commit e69773c8 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Merge branch 'lm-update-status-list' into 'master'

Update status for alert in alert management list

See merge request gitlab-org/gitlab!31276
parents 9ee7ad43 2a043397
......@@ -5,17 +5,21 @@ import {
GlLoadingIcon,
GlTable,
GlAlert,
GlNewDropdown,
GlNewDropdownItem,
GlIcon,
GlDropdown,
GlDropdownItem,
GlTabs,
GlTab,
GlBadge,
} from '@gitlab/ui';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import getAlerts from '../graphql/queries/getAlerts.query.graphql';
import { ALERTS_STATUS, ALERTS_STATUS_TABS } from '../constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
const tdClass = 'table-col d-flex d-md-table-cell align-items-center';
......@@ -53,6 +57,8 @@ export default {
},
{
key: 'status',
thClass: 'w-15p',
trClass: 'w-15p',
label: s__('AlertManagement|Status'),
tdClass: `${tdClass} rounded-bottom text-capitalize`,
},
......@@ -70,8 +76,9 @@ export default {
GlAlert,
GlDeprecatedButton,
TimeAgo,
GlNewDropdown,
GlNewDropdownItem,
GlDropdown,
GlDropdownItem,
GlIcon,
GlTabs,
GlTab,
GlBadge,
......@@ -140,6 +147,25 @@ export default {
filterALertsByStatus(tabIndex) {
this.statusFilter = this.$options.statusTabs[tabIndex].status;
},
capitalizeFirstCharacter,
updateAlertStatus(status, iid) {
this.$apollo
.mutate({
mutation: updateAlertStatus,
variables: {
iid,
status: status.toUpperCase(),
projectPath: this.projectPath,
},
})
.catch(() => {
createFlash(
s__(
'AlertManagement|There was an error while updating the status of the alert. Please try again.',
),
);
});
},
},
};
</script>
......@@ -190,11 +216,26 @@ export default {
</template>
<template #cell(status)="{ item }">
<gl-new-dropdown :text="item.status">
<gl-new-dropdown-item v-for="(label, field) in $options.statuses" :key="field">
<gl-dropdown
:text="capitalizeFirstCharacter(item.status.toLowerCase())"
class="w-100"
right
>
<gl-dropdown-item
v-for="(label, field) in $options.statuses"
:key="field"
@click="updateAlertStatus(label, item.iid)"
>
<span class="d-flex">
<gl-icon
class="flex-shrink-0 append-right-4"
:class="{ invisible: label.toUpperCase() !== item.status }"
name="mobile-issue-close"
/>
{{ label }}
</gl-new-dropdown-item>
</gl-new-dropdown>
</span>
</gl-dropdown-item>
</gl-dropdown>
</template>
<template #empty>
......
mutation ($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) {
updateAlertStatus(input: { iid: $iid, status: $status, projectPath: $projectPath }) {
errors
alert {
iid,
status,
}
}
}
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
import { parseBoolean } from '~/lib/utils/common_utils';
import AlertManagementList from './components/alert_management_list.vue';
......@@ -17,7 +18,20 @@ export default () => {
userCanEnableAlertManagement = parseBoolean(userCanEnableAlertManagement);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
defaultClient: createDefaultClient(
{},
{
cacheConfig: {
dataIdFromObject: object => {
// eslint-disable-next-line no-underscore-dangle
if (object.__typename === 'AlertManagementAlert') {
return object.iid;
}
return defaultDataIdFromObject(object);
},
},
},
),
});
return new Vue({
......
......@@ -25,7 +25,6 @@ describe('Selection Summary component', () => {
const dismissButton = () => wrapper.find(GlButton);
const dismissMessage = () => wrapper.find({ ref: 'dismiss-message' });
const formSelect = () => wrapper.find(GlFormSelect);
const createComponent = ({ props = {}, data = defaultData, mocks = defaultMocks }) => {
if (wrapper) {
throw new Error('Please avoid recreating components in the same spec');
......
......@@ -1796,6 +1796,9 @@ msgstr ""
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
msgid "AlertManagement|There was an error while updating the status of the alert. Please try again."
msgstr ""
msgid "AlertManagement|Tool"
msgstr ""
......
......@@ -4,16 +4,20 @@ import {
GlTable,
GlAlert,
GlLoadingIcon,
GlNewDropdown,
GlDropdown,
GlBadge,
GlTab,
GlDropdownItem,
} from '@gitlab/ui';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import createFlash from '~/flash';
import AlertManagementList from '~/alert_management/components/alert_management_list.vue';
import { ALERTS_STATUS_TABS } from '../../../../app/assets/javascripts/alert_management/constants';
import updateAlertStatus from '~/alert_management/graphql/mutations/update_alert_status.graphql';
import mockAlerts from '../mocks/alerts.json';
jest.mock('~/flash');
describe('AlertManagementList', () => {
let wrapper;
......@@ -21,10 +25,11 @@ describe('AlertManagementList', () => {
const findAlerts = () => wrapper.findAll('table tbody tr');
const findAlert = () => wrapper.find(GlAlert);
const findLoader = () => wrapper.find(GlLoadingIcon);
const findStatusDropdown = () => wrapper.find(GlNewDropdown);
const findStatusDropdown = () => wrapper.find(GlDropdown);
const findStatusFilterTabs = () => wrapper.findAll(GlTab);
const findNumberOfAlertsBadge = () => wrapper.findAll(GlBadge);
const findDateFields = () => wrapper.findAll(TimeAgo);
const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
function mountComponent({
props = {
......@@ -51,6 +56,7 @@ describe('AlertManagementList', () => {
},
mocks: {
$apollo: {
mutate: jest.fn(),
queries: {
alerts: {
loading,
......@@ -191,6 +197,7 @@ describe('AlertManagementList', () => {
alerts: [
{
iid: 1,
status: 'acknowledged',
startedAt: '2020-03-17T23:18:14.996Z',
endedAt: '2020-04-17T23:18:14.996Z',
},
......@@ -209,6 +216,7 @@ describe('AlertManagementList', () => {
alerts: [
{
iid: 1,
status: 'acknowledged',
startedAt: null,
endedAt: null,
},
......@@ -221,4 +229,52 @@ describe('AlertManagementList', () => {
});
});
});
describe('updating the alert status', () => {
const iid = '1527542';
const mockUpdatedMutationResult = {
data: {
updateAlertStatus: {
errors: [],
alert: {
iid,
status: 'acknowledged',
},
},
},
};
beforeEach(() => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, errored: false },
loading: false,
});
});
it('calls `$apollo.mutate` with `updateAlertStatus` mutation and variables containing `iid`, `status`, & `projectPath`', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockResolvedValue(mockUpdatedMutationResult);
findFirstStatusOption().vm.$emit('click');
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: updateAlertStatus,
variables: {
iid,
status: 'TRIGGERED',
projectPath: 'gitlab-org/gitlab',
},
});
});
it('calls `createFlash` when request fails', () => {
jest.spyOn(wrapper.vm.$apollo, 'mutate').mockReturnValue(Promise.reject(new Error()));
findFirstStatusOption().vm.$emit('click');
setImmediate(() => {
expect(createFlash).toHaveBeenCalledWith(
'There was an error while updating the status of the alert. Please try again.',
);
});
});
});
});
......@@ -9,8 +9,8 @@
"status": "triggered"
},
{
"iid": "1527542",
"title": "Some otherr alert Some otherr alert Some otherr alert Some otherr alert Some otherr alert Some otherr alert",
"iid": "1527543",
"title": "Some other alert Some other alert Some other alert Some other alert Some other alert Some other alert",
"severity": "MEDIUM",
"eventCount": 1,
"startedAt": "2020-04-17T23:18:14.996Z",
......@@ -18,7 +18,7 @@
"status": "acknowledged"
},
{
"iid": "1527542",
"iid": "1527544",
"title": "SyntaxError: Invalid or unexpected token",
"severity": "LOW",
"eventCount": 4,
......
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