Commit 7ebd83cc authored by Alexander Turinske's avatar Alexander Turinske

Add status change to drawer

- update status change component to be more flexible
- add tests

Changelog: added
parent 083498e7
...@@ -65,6 +65,8 @@ export default { ...@@ -65,6 +65,8 @@ export default {
:project-path="projectPath" :project-path="projectPath"
:alert="alert" :alert="alert"
:sidebar-collapsed="sidebarStatus" :sidebar-collapsed="sidebarStatus"
text-class="gl-text-gray-500"
class="gl-w-70p"
@toggle-sidebar="$emit('toggle-sidebar')" @toggle-sidebar="$emit('toggle-sidebar')"
@alert-error="$emit('alert-error', $event)" @alert-error="$emit('alert-error', $event)"
/> />
......
...@@ -34,6 +34,11 @@ export default { ...@@ -34,6 +34,11 @@ export default {
type: Boolean, type: Boolean,
required: false, required: false,
}, },
textClass: {
type: String,
required: false,
default: '',
},
}, },
data() { data() {
return { return {
...@@ -58,6 +63,9 @@ export default { ...@@ -58,6 +63,9 @@ export default {
} }
}, },
handleUpdating(updating) { handleUpdating(updating) {
if (!updating) {
this.$emit('alert-update');
}
this.isUpdating = updating; this.isUpdating = updating;
}, },
}, },
...@@ -66,7 +74,7 @@ export default { ...@@ -66,7 +74,7 @@ export default {
<template> <template>
<div <div
class="alert-status gl-py-5 gl-w-70p" class="alert-status gl-py-5"
:class="{ 'gl-border-b-1 gl-border-b-solid gl-border-b-gray-100': !sidebarCollapsed }" :class="{ 'gl-border-b-1 gl-border-b-solid gl-border-b-gray-100': !sidebarCollapsed }"
> >
<template v-if="sidebarCollapsed"> <template v-if="sidebarCollapsed">
...@@ -118,7 +126,7 @@ export default { ...@@ -118,7 +126,7 @@ export default {
class="value gl-m-0" class="value gl-m-0"
:class="{ 'no-value': !statuses[alert.status] }" :class="{ 'no-value': !statuses[alert.status] }"
> >
<span v-if="statuses[alert.status]" class="gl-text-gray-500" data-testid="status"> <span v-if="statuses[alert.status]" :class="textClass" data-testid="status">
{{ statuses[alert.status] }} {{ statuses[alert.status] }}
</span> </span>
<span v-else> <span v-else>
......
...@@ -228,7 +228,7 @@ By default, the list doesn't display resolved or dismissed alerts. ...@@ -228,7 +228,7 @@ By default, the list doesn't display resolved or dismissed alerts.
![Policy Alert List](img/threat_monitoring_policy_alert_list_v13_12.png) ![Policy Alert List](img/threat_monitoring_policy_alert_list_v13_12.png)
Clicking an alert's row opens the alert drawer, which shows more information about the alert. A user Clicking an alert's row opens the alert drawer, which shows more information about the alert. A user
can also create an incident from the alert in the alert drawer. can also create an incident from the alert and update the alert status in the alert drawer.
Clicking an alert's name takes the user to the [alert details page](../../../operations/incident_management/alerts.md#alert-details-page). Clicking an alert's name takes the user to the [alert details page](../../../operations/incident_management/alerts.md#alert-details-page).
......
...@@ -4,6 +4,7 @@ import * as Sentry from '@sentry/browser'; ...@@ -4,6 +4,7 @@ import * as Sentry from '@sentry/browser';
import { capitalizeFirstCharacter, splitCamelCase } from '~/lib/utils/text_utility'; import { capitalizeFirstCharacter, splitCamelCase } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import { __ } from '~/locale'; import { __ } from '~/locale';
import SidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
import createIssueMutation from '~/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql'; import createIssueMutation from '~/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql';
import getAlertDetailsQuery from '~/vue_shared/alert_details/graphql/queries/alert_details.query.graphql'; import getAlertDetailsQuery from '~/vue_shared/alert_details/graphql/queries/alert_details.query.graphql';
import { getContentWrapperHeight } from '../../utils'; import { getContentWrapperHeight } from '../../utils';
...@@ -16,6 +17,7 @@ export default { ...@@ -16,6 +17,7 @@ export default {
ERRORS: { ...DRAWER_ERRORS }, ERRORS: { ...DRAWER_ERRORS },
}, },
components: { components: {
SidebarStatus,
GlAlert, GlAlert,
GlButton, GlButton,
GlDrawer, GlDrawer,
...@@ -115,6 +117,9 @@ export default { ...@@ -115,6 +117,9 @@ export default {
getDrawerHeaderHeight() { getDrawerHeaderHeight() {
return getContentWrapperHeight('.js-threat-monitoring-container-wrapper'); return getContentWrapperHeight('.js-threat-monitoring-container-wrapper');
}, },
handleAlertUpdate() {
this.$emit('alert-update');
},
handleAlertError({ type, error }) { handleAlertError({ type, error }) {
this.errorMessage = this.$options.i18n.ERRORS[type]; this.errorMessage = this.$options.i18n.ERRORS[type];
Sentry.captureException(error); Sentry.captureException(error);
...@@ -154,6 +159,12 @@ export default { ...@@ -154,6 +159,12 @@ export default {
<gl-alert v-if="errored" variant="danger" :dismissible="false" contained> <gl-alert v-if="errored" variant="danger" :dismissible="false" contained>
{{ errorMessage }} {{ errorMessage }}
</gl-alert> </gl-alert>
<sidebar-status
:alert="selectedAlert"
:project-path="projectPath"
text-class="gl-font-weight-bold"
@alert-update="handleAlertUpdate"
/>
<div v-if="isLoadingDetails"> <div v-if="isLoadingDetails">
<div v-for="row in $options.ALERT_DETAILS_LOADING_ROWS" :key="row" class="gl-mb-5"> <div v-for="row in $options.ALERT_DETAILS_LOADING_ROWS" :key="row" class="gl-mb-5">
<gl-skeleton-loader :lines="2" :width="400" /> <gl-skeleton-loader :lines="2" :width="400" />
......
...@@ -58,6 +58,9 @@ export default { ...@@ -58,6 +58,9 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
provide: {
statuses: STATUSES,
},
inject: ['documentationPath', 'projectPath'], inject: ['documentationPath', 'projectPath'],
apollo: { apollo: {
alerts: { alerts: {
...@@ -74,6 +77,11 @@ export default { ...@@ -74,6 +77,11 @@ export default {
update: ({ project }) => project?.alertManagementAlerts.nodes || [], update: ({ project }) => project?.alertManagementAlerts.nodes || [],
result({ data }) { result({ data }) {
this.pageInfo = data?.project?.alertManagementAlerts?.pageInfo || {}; this.pageInfo = data?.project?.alertManagementAlerts?.pageInfo || {};
if (this.selectedAlert) {
this.selectedAlert = data?.project?.alertManagementAlerts?.nodes?.find(
(alert) => alert.iid === this.selectedAlert.iid,
);
}
}, },
error() { error() {
this.errored = true; this.errored = true;
...@@ -143,7 +151,7 @@ export default { ...@@ -143,7 +151,7 @@ export default {
}, },
handleAlertDeselect() { handleAlertDeselect() {
this.isAlertDrawerOpen = false; this.isAlertDrawerOpen = false;
this.selectedAlert = {}; this.selectedAlert = null;
}, },
handleAlertError(msg) { handleAlertError(msg) {
this.errored = true; this.errored = true;
...@@ -312,6 +320,7 @@ export default { ...@@ -312,6 +320,7 @@ export default {
v-if="selectedAlert" v-if="selectedAlert"
:is-alert-drawer-open="isAlertDrawerOpen" :is-alert-drawer-open="isAlertDrawerOpen"
:selected-alert="selectedAlert" :selected-alert="selectedAlert"
@alert-update="handleStatusUpdate"
@deselect-alert="handleAlertDeselect" @deselect-alert="handleAlertDeselect"
/> />
</div> </div>
......
---
title: Add alert status change dropdown to drawer
merge_request: 61832
author:
type: added
...@@ -8,6 +8,7 @@ import createMockApollo from 'helpers/mock_apollo_helper'; ...@@ -8,6 +8,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import SidebarStatus from '~/vue_shared/alert_details/components/sidebar/sidebar_status.vue';
import getAlertDetailsQuery from '~/vue_shared/alert_details/graphql/queries/alert_details.query.graphql'; import getAlertDetailsQuery from '~/vue_shared/alert_details/graphql/queries/alert_details.query.graphql';
import { import {
erroredGetAlertDetailsQuerySpy, erroredGetAlertDetailsQuerySpy,
...@@ -48,6 +49,7 @@ describe('Alert Drawer', () => { ...@@ -48,6 +49,7 @@ describe('Alert Drawer', () => {
const findIssueLink = () => wrapper.findByTestId('issue-link'); const findIssueLink = () => wrapper.findByTestId('issue-link');
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader); const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findDetails = () => wrapper.findByTestId('details-list'); const findDetails = () => wrapper.findByTestId('details-list');
const findStatus = () => wrapper.findComponent(SidebarStatus);
const createWrapper = ({ const createWrapper = ({
$apollo, $apollo,
...@@ -160,4 +162,12 @@ describe('Alert Drawer', () => { ...@@ -160,4 +162,12 @@ describe('Alert Drawer', () => {
expect(captureExceptionSpy.mock.calls[0][0].message).toBe(errorMessage); expect(captureExceptionSpy.mock.calls[0][0].message).toBe(errorMessage);
}); });
}); });
it('handles an alert status update', async () => {
createWrapper({ props: { selectedAlert: mockAlerts[0] } });
expect(wrapper.emitted('alert-update')).toBeUndefined();
findStatus().vm.$emit('alert-update');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('alert-update')).toEqual([[]]);
});
}); });
...@@ -121,6 +121,14 @@ describe('Alert Details Sidebar Status', () => { ...@@ -121,6 +121,14 @@ describe('Alert Details Sidebar Status', () => {
expect(findStatus().text()).toBe('Triggered'); expect(findStatus().text()).toBe('Triggered');
}); });
it('emits "alert-update" when the status has been updated', async () => {
mountComponent({ sidebarCollapsed: false });
expect(wrapper.emitted('alert-update')).toBeUndefined();
findAlertStatus().vm.$emit('handle-updating');
await wrapper.vm.$nextTick();
expect(wrapper.emitted('alert-update')).toEqual([[]]);
});
it('renders translated statuses', () => { it('renders translated statuses', () => {
const status = 'TEST'; const status = 'TEST';
const statuses = { [status]: 'Test' }; const statuses = { [status]: 'Test' };
......
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