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 {
:project-path="projectPath"
:alert="alert"
:sidebar-collapsed="sidebarStatus"
text-class="gl-text-gray-500"
class="gl-w-70p"
@toggle-sidebar="$emit('toggle-sidebar')"
@alert-error="$emit('alert-error', $event)"
/>
......
......@@ -34,6 +34,11 @@ export default {
type: Boolean,
required: false,
},
textClass: {
type: String,
required: false,
default: '',
},
},
data() {
return {
......@@ -58,6 +63,9 @@ export default {
}
},
handleUpdating(updating) {
if (!updating) {
this.$emit('alert-update');
}
this.isUpdating = updating;
},
},
......@@ -66,7 +74,7 @@ export default {
<template>
<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 }"
>
<template v-if="sidebarCollapsed">
......@@ -118,7 +126,7 @@ export default {
class="value gl-m-0"
: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] }}
</span>
<span v-else>
......
......@@ -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)
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).
......
......@@ -4,6 +4,7 @@ import * as Sentry from '@sentry/browser';
import { capitalizeFirstCharacter, splitCamelCase } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
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 getAlertDetailsQuery from '~/vue_shared/alert_details/graphql/queries/alert_details.query.graphql';
import { getContentWrapperHeight } from '../../utils';
......@@ -16,6 +17,7 @@ export default {
ERRORS: { ...DRAWER_ERRORS },
},
components: {
SidebarStatus,
GlAlert,
GlButton,
GlDrawer,
......@@ -115,6 +117,9 @@ export default {
getDrawerHeaderHeight() {
return getContentWrapperHeight('.js-threat-monitoring-container-wrapper');
},
handleAlertUpdate() {
this.$emit('alert-update');
},
handleAlertError({ type, error }) {
this.errorMessage = this.$options.i18n.ERRORS[type];
Sentry.captureException(error);
......@@ -154,6 +159,12 @@ export default {
<gl-alert v-if="errored" variant="danger" :dismissible="false" contained>
{{ errorMessage }}
</gl-alert>
<sidebar-status
:alert="selectedAlert"
:project-path="projectPath"
text-class="gl-font-weight-bold"
@alert-update="handleAlertUpdate"
/>
<div v-if="isLoadingDetails">
<div v-for="row in $options.ALERT_DETAILS_LOADING_ROWS" :key="row" class="gl-mb-5">
<gl-skeleton-loader :lines="2" :width="400" />
......
......@@ -58,6 +58,9 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
provide: {
statuses: STATUSES,
},
inject: ['documentationPath', 'projectPath'],
apollo: {
alerts: {
......@@ -74,6 +77,11 @@ export default {
update: ({ project }) => project?.alertManagementAlerts.nodes || [],
result({ data }) {
this.pageInfo = data?.project?.alertManagementAlerts?.pageInfo || {};
if (this.selectedAlert) {
this.selectedAlert = data?.project?.alertManagementAlerts?.nodes?.find(
(alert) => alert.iid === this.selectedAlert.iid,
);
}
},
error() {
this.errored = true;
......@@ -143,7 +151,7 @@ export default {
},
handleAlertDeselect() {
this.isAlertDrawerOpen = false;
this.selectedAlert = {};
this.selectedAlert = null;
},
handleAlertError(msg) {
this.errored = true;
......@@ -312,6 +320,7 @@ export default {
v-if="selectedAlert"
:is-alert-drawer-open="isAlertDrawerOpen"
:selected-alert="selectedAlert"
@alert-update="handleStatusUpdate"
@deselect-alert="handleAlertDeselect"
/>
</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';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
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 {
erroredGetAlertDetailsQuerySpy,
......@@ -48,6 +49,7 @@ describe('Alert Drawer', () => {
const findIssueLink = () => wrapper.findByTestId('issue-link');
const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findDetails = () => wrapper.findByTestId('details-list');
const findStatus = () => wrapper.findComponent(SidebarStatus);
const createWrapper = ({
$apollo,
......@@ -160,4 +162,12 @@ describe('Alert Drawer', () => {
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', () => {
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', () => {
const 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