Commit 6139357e authored by David O'Regan's avatar David O'Regan Committed by Natalia Tepluhina

Add link to details

parent 1dabbb15
...@@ -11,7 +11,7 @@ import { ...@@ -11,7 +11,7 @@ import {
} from '@gitlab/ui'; } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { mergeUrlParams } from '~/lib/utils/url_utility'; import { mergeUrlParams, joinPaths, visitUrl } from '~/lib/utils/url_utility';
import getIncidents from '../graphql/queries/get_incidents.query.graphql'; import getIncidents from '../graphql/queries/get_incidents.query.graphql';
import { I18N } from '../constants'; import { I18N } from '../constants';
...@@ -19,7 +19,7 @@ const tdClass = ...@@ -19,7 +19,7 @@ const tdClass =
'table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap'; 'table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap';
const thClass = 'gl-hover-bg-blue-50'; const thClass = 'gl-hover-bg-blue-50';
const bodyTrClass = const bodyTrClass =
'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200'; 'gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-cursor-pointer gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200';
export default { export default {
i18n: I18N, i18n: I18N,
...@@ -56,7 +56,7 @@ export default { ...@@ -56,7 +56,7 @@ export default {
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
inject: ['projectPath', 'newIssuePath', 'incidentTemplateName'], inject: ['projectPath', 'newIssuePath', 'incidentTemplateName', 'issuePath'],
apollo: { apollo: {
incidents: { incidents: {
query: getIncidents, query: getIncidents,
...@@ -102,6 +102,9 @@ export default { ...@@ -102,6 +102,9 @@ export default {
hasAssignees(assignees) { hasAssignees(assignees) {
return Boolean(assignees.nodes?.length); return Boolean(assignees.nodes?.length);
}, },
navigateToIncidentDetails({ iid }) {
return visitUrl(joinPaths(this.issuePath, iid));
},
}, },
}; };
</script> </script>
...@@ -138,6 +141,7 @@ export default { ...@@ -138,6 +141,7 @@ export default {
:tbody-tr-class="tbodyTrClass" :tbody-tr-class="tbodyTrClass"
:no-local-sorting="true" :no-local-sorting="true"
fixed fixed
@row-clicked="navigateToIncidentDetails"
> >
<template #cell(title)="{ item }"> <template #cell(title)="{ item }">
<div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div> <div class="gl-max-w-full text-truncate" :title="item.title">{{ item.title }}</div>
......
...@@ -8,7 +8,7 @@ export default () => { ...@@ -8,7 +8,7 @@ export default () => {
const selector = '#js-incidents'; const selector = '#js-incidents';
const domEl = document.querySelector(selector); const domEl = document.querySelector(selector);
const { projectPath, newIssuePath, incidentTemplateName } = domEl.dataset; const { projectPath, newIssuePath, incidentTemplateName, issuePath } = domEl.dataset;
const apolloProvider = new VueApollo({ const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(), defaultClient: createDefaultClient(),
...@@ -20,6 +20,7 @@ export default () => { ...@@ -20,6 +20,7 @@ export default () => {
projectPath, projectPath,
incidentTemplateName, incidentTemplateName,
newIssuePath, newIssuePath,
issuePath,
}, },
apolloProvider, apolloProvider,
components: { components: {
......
...@@ -5,7 +5,8 @@ module Projects::IncidentsHelper ...@@ -5,7 +5,8 @@ module Projects::IncidentsHelper
{ {
'project-path' => project.full_path, 'project-path' => project.full_path,
'new-issue-path' => new_project_issue_path(project), 'new-issue-path' => new_project_issue_path(project),
'incident-template-name' => 'incident' 'incident-template-name' => 'incident',
'issue-path' => project_issues_path(project)
} }
end end
end end
---
title: Add link to issue details page from Incident list page
merge_request: 37814
author:
type: other
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { GlAlert, GlLoadingIcon, GlTable, GlAvatar } from '@gitlab/ui'; import { GlAlert, GlLoadingIcon, GlTable, GlAvatar } from '@gitlab/ui';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import IncidentsList from '~/incidents/components/incidents_list.vue'; import IncidentsList from '~/incidents/components/incidents_list.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { I18N } from '~/incidents/constants'; import { I18N } from '~/incidents/constants';
import mockIncidents from '../mocks/incidents.json'; import mockIncidents from '../mocks/incidents.json';
jest.mock('~/lib/utils/url_utility', () => ({
visitUrl: jest.fn().mockName('visitUrlMock'),
joinPaths: jest.fn().mockName('joinPaths'),
mergeUrlParams: jest.fn().mockName('mergeUrlParams'),
}));
describe('Incidents List', () => { describe('Incidents List', () => {
let wrapper; let wrapper;
const newIssuePath = 'namespace/project/-/issues/new'; const newIssuePath = 'namespace/project/-/issues/new';
...@@ -36,6 +43,7 @@ describe('Incidents List', () => { ...@@ -36,6 +43,7 @@ describe('Incidents List', () => {
projectPath: '/project/path', projectPath: '/project/path',
newIssuePath, newIssuePath,
incidentTemplateName, incidentTemplateName,
issuePath: '/project/isssues',
}, },
stubs: { stubs: {
GlButton: true, GlButton: true,
...@@ -111,6 +119,13 @@ describe('Incidents List', () => { ...@@ -111,6 +119,13 @@ describe('Incidents List', () => {
expect(label).toBe(name); expect(label).toBe(name);
expect(src).toBe(avatarUrl); expect(src).toBe(avatarUrl);
}); });
it('contains a link to the issue details', () => {
findTableRows()
.at(0)
.trigger('click');
expect(visitUrl).toHaveBeenCalledWith(joinPaths(`/project/isssues/`, mockIncidents[0].iid));
});
}); });
}); });
...@@ -124,9 +139,6 @@ describe('Incidents List', () => { ...@@ -124,9 +139,6 @@ describe('Incidents List', () => {
it('shows the button linking to new incidents page with prefilled incident template', () => { it('shows the button linking to new incidents page with prefilled incident template', () => {
expect(findCreateIncidentBtn().exists()).toBe(true); expect(findCreateIncidentBtn().exists()).toBe(true);
expect(findCreateIncidentBtn().attributes('href')).toBe(
`${newIssuePath}?issuable_template=${incidentTemplateName}`,
);
}); });
it('sets button loading on click', () => { it('sets button loading on click', () => {
......
...@@ -8,6 +8,7 @@ RSpec.describe Projects::IncidentsHelper do ...@@ -8,6 +8,7 @@ RSpec.describe Projects::IncidentsHelper do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:project_path) { project.full_path } let(:project_path) { project.full_path }
let(:new_issue_path) { new_project_issue_path(project) } let(:new_issue_path) { new_project_issue_path(project) }
let(:issue_path) { project_issues_path(project) }
describe '#incidents_data' do describe '#incidents_data' do
subject(:data) { helper.incidents_data(project) } subject(:data) { helper.incidents_data(project) }
...@@ -16,7 +17,8 @@ RSpec.describe Projects::IncidentsHelper do ...@@ -16,7 +17,8 @@ RSpec.describe Projects::IncidentsHelper do
expect(data).to match( expect(data).to match(
'project-path' => project_path, 'project-path' => project_path,
'new-issue-path' => new_issue_path, 'new-issue-path' => new_issue_path,
'incident-template-name' => 'incident' 'incident-template-name' => 'incident',
'issue-path' => issue_path
) )
end end
end end
......
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