Commit d0155a7c authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'lm-sorting-list' into 'master'

Implement sorting by column in alert management list

See merge request gitlab-org/gitlab!32478
parents 69d6ac52 8ad897d1
......@@ -21,11 +21,12 @@ import getAlerts from '../graphql/queries/get_alerts.query.graphql';
import getAlertsCountByStatus from '../graphql/queries/get_count_by_status.query.graphql';
import { ALERTS_STATUS, ALERTS_STATUS_TABS, ALERTS_SEVERITY_LABELS } from '../constants';
import updateAlertStatus from '../graphql/mutations/update_alert_status.graphql';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { capitalizeFirstCharacter, convertToSnakeCase } from '~/lib/utils/text_utility';
const tdClass = 'table-col d-flex d-md-table-cell align-items-center';
const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 hover-bg-blue-50 hover-gl-cursor-pointer hover-gl-border-b-solid hover-gl-border-blue-200';
const findDefaultSortColumn = () => document.querySelector('.js-started-at');
export default {
i18n: {
......@@ -41,34 +42,41 @@ export default {
key: 'severity',
label: s__('AlertManagement|Severity'),
tdClass: `${tdClass} rounded-top text-capitalize`,
sortable: true,
},
{
key: 'startedAt',
key: 'startTime',
label: s__('AlertManagement|Start time'),
thClass: 'js-started-at',
tdClass,
sortable: true,
},
{
key: 'endedAt',
key: 'endTime',
label: s__('AlertManagement|End time'),
tdClass,
sortable: true,
},
{
key: 'title',
label: s__('AlertManagement|Alert'),
thClass: 'w-30p',
thClass: 'w-30p alert-title',
tdClass,
sortable: false,
},
{
key: 'eventCount',
key: 'eventsCount',
label: s__('AlertManagement|Events'),
thClass: 'text-right gl-pr-9',
thClass: 'text-right gl-pr-9 w-3rem',
tdClass: `${tdClass} text-md-right`,
sortable: true,
},
{
key: 'status',
thClass: 'w-15p',
label: s__('AlertManagement|Status'),
tdClass: `${tdClass} rounded-bottom`,
sortable: true,
},
],
statuses: {
......@@ -122,6 +130,7 @@ export default {
return {
projectPath: this.projectPath,
statuses: this.statusFilter,
sort: this.sort,
};
},
update(data) {
......@@ -148,6 +157,7 @@ export default {
errored: false,
isAlertDismissed: false,
isErrorAlertDismissed: false,
sort: 'START_TIME_ASC',
statusFilter: this.$options.statusTabs[4].filters,
};
},
......@@ -170,10 +180,22 @@ export default {
return !this.loading && this.hasAlerts ? bodyTrClass : '';
},
},
mounted() {
findDefaultSortColumn().ariaSort = 'ascending';
},
methods: {
filterAlertsByStatus(tabIndex) {
this.statusFilter = this.$options.statusTabs[tabIndex].filters;
},
fetchSortedData({ sortBy, sortDesc }) {
const sortDirection = sortDesc ? 'DESC' : 'ASC';
const sortColumn = convertToSnakeCase(sortBy).toUpperCase();
if (sortBy !== 'startTime') {
findDefaultSortColumn().ariaSort = 'none';
}
this.sort = `${sortColumn}_${sortDirection}`;
},
capitalizeFirstCharacter,
updateAlertStatus(status, iid) {
this.$apollo
......@@ -235,7 +257,10 @@ export default {
:busy="loading"
stacked="md"
:tbody-tr-class="tbodyTrClass"
:no-local-sorting="true"
sort-icon-left
@row-clicked="navigateToAlertDetails"
@sort-changed="fetchSortedData"
>
<template #cell(severity)="{ item }">
<div
......@@ -252,13 +277,17 @@ export default {
</div>
</template>
<template #cell(startedAt)="{ item }">
<template #cell(startTime)="{ item }">
<time-ago v-if="item.startedAt" :time="item.startedAt" />
</template>
<template #cell(endedAt)="{ item }">
<template #cell(endTime)="{ item }">
<time-ago v-if="item.endedAt" :time="item.endedAt" />
</template>
<!-- TODO: Remove after: https://gitlab.com/gitlab-org/gitlab/-/issues/218467 -->
<template #cell(eventsCount)="{ item }">
{{ item.eventCount }}
</template>
<template #cell(title)="{ item }">
<div class="gl-max-w-full text-truncate">{{ item.title }}</div>
......
#import "../fragments/list_item.fragment.graphql"
query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!]) {
query getAlerts($projectPath: ID!, $statuses: [AlertManagementStatus!], $sort: AlertManagementAlertSort ) {
project(fullPath: $projectPath) {
alertManagementAlerts(statuses: $statuses) {
alertManagementAlerts(statuses: $statuses, sort: $sort) {
nodes {
...AlertListItem
}
......
......@@ -55,3 +55,26 @@ $tooltip-padding-y: 0.5rem;
$tooltip-padding-x: 0.75rem;
$tooltip-arrow-height: 0.5rem;
$tooltip-arrow-width: 1rem;
$b-table-sort-icon-bg-ascending: url('data:image/svg+xml, <svg \
xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="4 0 8 16"> \
<path style="fill: #666;" fill-rule="evenodd" d="M11.707085,11.7071 \
L7.999975,15.4142 L4.292875,11.7071 C3.902375,11.3166 3.902375, \
10.6834 4.292875,10.2929 C4.683375,9.90237 \
5.316575,9.90237 5.707075,10.2929 L6.999975, \
11.5858 L6.999975,2 C6.999975,1.44771 \
7.447695,1 7.999975,1 C8.552255,1 8.999975,1.44771 \
8.999975,2 L8.999975,11.5858 L10.292865,10.2929 C10.683395 \
,9.90237 11.316555,9.90237 11.707085,10.2929 \
C12.097605,10.6834 12.097605,11.3166 11.707085,11.7071 Z"/> \
</svg>') !default;
$b-table-sort-icon-bg-descending: url('data:image/svg+xml,<svg \
xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="4 0 8 16"> \
<path style="fill: #666;" fill-rule="evenodd" d="M4.29289,4.2971 L8,0.59 \
L11.7071,4.2971 C12.0976,4.6876 \
12.0976,5.3208 11.7071,5.7113 C11.3166,6.10183 10.6834, \
6.10183 10.2929,5.7113 L9,4.4184 L9,14.0042 C9,14.55649 \
8.55228,15.0042 8,15.0042 C7.44772,15.0042 7,14.55649 \
7,14.0042 L7,4.4184 L5.70711,5.7113 C5.31658,6.10183 4.68342,6.10183 4.29289,5.7113 \
C3.90237,5.3208 3.90237,4.6876 4.29289,4.2971 Z"/> \
</svg> ') !default;
$b-table-sort-icon-bg-not-sorted: '';
......@@ -28,8 +28,19 @@
td,
th {
@include gl-p-5;
// TODO: There is no gl-pl-9 utlity for this padding, to be done and then removed.
padding-left: 1.25rem;
@include gl-py-5;
@include gl-outline-none;
border: 0; // Remove cell border styling so that we can set border styling per row
&.event-count {
@include gl-pr-9;
}
&.alert-title {
@include gl-pointer-events-none;
}
}
th {
......
---
title: Adds sorting by column to alert management list
merge_request: 32478
author:
type: added
......@@ -38,6 +38,7 @@ describe('AlertManagementList', () => {
const findDateFields = () => wrapper.findAll(TimeAgo);
const findFirstStatusOption = () => findStatusDropdown().find(GlDropdownItem);
const findSeverityFields = () => wrapper.findAll('[data-testid="severityField"]');
const findSeverityColumnHeader = () => wrapper.findAll('th').at(0);
const alertsCount = {
acknowledged: 6,
......@@ -80,7 +81,10 @@ describe('AlertManagementList', () => {
});
}
const mockStartedAtCol = {};
beforeEach(() => {
jest.spyOn(document, 'querySelector').mockReturnValue(mockStartedAtCol);
mountComponent();
});
......@@ -284,6 +288,34 @@ describe('AlertManagementList', () => {
});
});
describe('sorting the alert list by column', () => {
beforeEach(() => {
mountComponent({
props: { alertManagementEnabled: true, userCanEnableAlertManagement: true },
data: { alerts: mockAlerts, errored: false, sort: 'START_TIME_ASC', alertsCount },
loading: false,
});
});
it('updates sort with new direction and column key', () => {
findSeverityColumnHeader().trigger('click');
expect(wrapper.vm.$data.sort).toEqual('SEVERITY_ASC');
findSeverityColumnHeader().trigger('click');
expect(wrapper.vm.$data.sort).toEqual('SEVERITY_DESC');
});
it('updates the `ariaSort` attribute so the sort icon appears in the proper column', () => {
expect(mockStartedAtCol.ariaSort).toEqual('ascending');
findSeverityColumnHeader().trigger('click');
expect(mockStartedAtCol.ariaSort).toEqual('none');
});
});
describe('updating the alert status', () => {
const iid = '1527542';
const mockUpdatedMutationResult = {
......
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