Commit 2277b124 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo Committed by Sincheol (David) Kim

Include the project name VSA stage records

For group VSA we should include the project name
for each record in the stage table

Expose project object to VSA stage records

Changelog: added
EE: true
parent dfdc2855
...@@ -89,6 +89,11 @@ export default { ...@@ -89,6 +89,11 @@ export default {
required: false, required: false,
default: true, default: true,
}, },
includeProjectName: {
type: Boolean,
required: false,
default: false,
},
}, },
data() { data() {
if (this.pagination) { if (this.pagination) {
...@@ -144,8 +149,13 @@ export default { ...@@ -144,8 +149,13 @@ export default {
isMrLink(url = '') { isMrLink(url = '') {
return url.includes('/merge_request'); return url.includes('/merge_request');
}, },
itemId({ url, iid }) { itemId({ iid, projectPath }, separator = '#') {
return this.isMrLink(url) ? `!${iid}` : `#${iid}`; const prefix = this.includeProjectName ? projectPath : '';
return `${prefix}${separator}${iid}`;
},
itemDisplayName(item) {
const separator = this.isMrLink(item.url) ? '!' : '#';
return this.itemId(item, separator);
}, },
itemTitle(item) { itemTitle(item) {
return item.title || item.name; return item.title || item.name;
...@@ -201,8 +211,11 @@ export default { ...@@ -201,8 +211,11 @@ export default {
<div data-testid="vsa-stage-event"> <div data-testid="vsa-stage-event">
<div v-if="item.id" data-testid="vsa-stage-content"> <div v-if="item.id" data-testid="vsa-stage-content">
<p class="gl-m-0"> <p class="gl-m-0">
<gl-link class="gl-text-black-normal pipeline-id" :href="item.url" <gl-link
>#{{ item.id }}</gl-link data-testid="vsa-stage-event-link"
class="gl-text-black-normal pipeline-id"
:href="item.url"
>{{ itemId(item.id, '#') }}</gl-link
> >
<gl-icon :size="16" name="fork" /> <gl-icon :size="16" name="fork" />
<gl-link <gl-link
...@@ -240,7 +253,12 @@ export default { ...@@ -240,7 +253,12 @@ export default {
<gl-link class="gl-text-black-normal" :href="item.url">{{ itemTitle(item) }}</gl-link> <gl-link class="gl-text-black-normal" :href="item.url">{{ itemTitle(item) }}</gl-link>
</h5> </h5>
<p class="gl-m-0"> <p class="gl-m-0">
<gl-link class="gl-text-black-normal" :href="item.url">{{ itemId(item) }}</gl-link> <gl-link
data-testid="vsa-stage-event-link"
class="gl-text-black-normal"
:href="item.url"
>{{ itemDisplayName(item) }}</gl-link
>
<span class="gl-font-lg">&middot;</span> <span class="gl-font-lg">&middot;</span>
<span data-testid="vsa-stage-event-date"> <span data-testid="vsa-stage-event-date">
{{ s__('OpenedNDaysAgo|Opened') }} {{ s__('OpenedNDaysAgo|Opened') }}
......
...@@ -9,6 +9,9 @@ class AnalyticsBuildEntity < Grape::Entity ...@@ -9,6 +9,9 @@ class AnalyticsBuildEntity < Grape::Entity
expose :ref, as: :branch expose :ref, as: :branch
expose :short_sha expose :short_sha
expose :author, using: UserEntity expose :author, using: UserEntity
expose :project_path do |build|
build.project.path
end
expose :started_at, as: :date do |build| expose :started_at, as: :date do |build|
interval_in_words(build[:started_at]) interval_in_words(build[:started_at])
......
...@@ -6,6 +6,9 @@ class AnalyticsIssueEntity < Grape::Entity ...@@ -6,6 +6,9 @@ class AnalyticsIssueEntity < Grape::Entity
expose :title expose :title
expose :author, using: UserEntity expose :author, using: UserEntity
expose :project_path do |object|
object[:project_path]
end
expose :iid do |object| expose :iid do |object|
object[:iid].to_s object[:iid].to_s
......
...@@ -213,6 +213,7 @@ export default { ...@@ -213,6 +213,7 @@ export default {
:empty-state-message="selectedStageError" :empty-state-message="selectedStageError"
:no-data-svg-path="noDataSvgPath" :no-data-svg-path="noDataSvgPath"
:pagination="pagination" :pagination="pagination"
include-project-name
@handleUpdatePagination="onHandleUpdatePagination" @handleUpdatePagination="onHandleUpdatePagination"
/> />
<url-sync v-if="selectedStageReady" :query="query" /> <url-sync v-if="selectedStageReady" :query="query" />
......
...@@ -319,6 +319,10 @@ describe('EE Value Stream Analytics component', () => { ...@@ -319,6 +319,10 @@ describe('EE Value Stream Analytics component', () => {
displaysStageTable(true); displaysStageTable(true);
}); });
it('sets the `includeProjectName` prop on stage table', () => {
expect(findStageTable().props('includeProjectName')).toBe(true);
});
it('displays the path navigation', () => { it('displays the path navigation', () => {
displaysPathNavigation(true); displaysPathNavigation(true);
}); });
......
...@@ -24,6 +24,7 @@ const findTable = () => wrapper.findComponent(GlTable); ...@@ -24,6 +24,7 @@ const findTable = () => wrapper.findComponent(GlTable);
const findTableHead = () => wrapper.find('thead'); const findTableHead = () => wrapper.find('thead');
const findTableHeadColumns = () => findTableHead().findAll('th'); const findTableHeadColumns = () => findTableHead().findAll('th');
const findStageEventTitle = (ev) => extendedWrapper(ev).findByTestId('vsa-stage-event-title'); const findStageEventTitle = (ev) => extendedWrapper(ev).findByTestId('vsa-stage-event-title');
const findStageEventLink = (ev) => extendedWrapper(ev).findByTestId('vsa-stage-event-link');
const findStageTime = () => wrapper.findByTestId('vsa-stage-event-time'); const findStageTime = () => wrapper.findByTestId('vsa-stage-event-time');
const findIcon = (name) => wrapper.findByTestId(`${name}-icon`); const findIcon = (name) => wrapper.findByTestId(`${name}-icon`);
...@@ -86,6 +87,15 @@ describe('StageTable', () => { ...@@ -86,6 +87,15 @@ describe('StageTable', () => {
expect(titles[index]).toBe(ev.title); expect(titles[index]).toBe(ev.title);
}); });
}); });
it('will not display the project name in the record link', () => {
const evs = findStageEvents();
const links = evs.wrappers.map((ev) => findStageEventLink(ev).text());
issueEventItems.forEach((ev, index) => {
expect(links[index]).toBe(`#${ev.iid}`);
});
});
}); });
describe('default event', () => { describe('default event', () => {
...@@ -187,6 +197,21 @@ describe('StageTable', () => { ...@@ -187,6 +197,21 @@ describe('StageTable', () => {
}); });
}); });
describe('includeProjectName set', () => {
beforeEach(() => {
wrapper = createComponent({ includeProjectName: true });
});
it('will display the project name in the record link', () => {
const evs = findStageEvents();
const links = evs.wrappers.map((ev) => findStageEventLink(ev).text());
issueEventItems.forEach((ev, index) => {
expect(links[index]).toBe(`${ev.projectPath}#${ev.iid}`);
});
});
});
describe('Pagination', () => { describe('Pagination', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createComponent(); wrapper = createComponent();
......
...@@ -27,6 +27,10 @@ RSpec.describe AnalyticsBuildEntity do ...@@ -27,6 +27,10 @@ RSpec.describe AnalyticsBuildEntity do
expect(subject).to include(:author) expect(subject).to include(:author)
end end
it 'contains the project path' do
expect(subject).to include(:project_path)
end
it 'does not contain sensitive information' do it 'does not contain sensitive information' do
expect(subject).not_to include(/token/) expect(subject).not_to include(/token/)
expect(subject).not_to include(/variables/) expect(subject).not_to include(/variables/)
......
...@@ -32,6 +32,10 @@ RSpec.describe AnalyticsIssueEntity do ...@@ -32,6 +32,10 @@ RSpec.describe AnalyticsIssueEntity do
expect(subject).to include(:author) expect(subject).to include(:author)
end end
it 'contains the project path' do
expect(subject).to include(:project_path)
end
it 'does not contain sensitive information' do it 'does not contain sensitive information' do
expect(subject).not_to include(/token/) expect(subject).not_to include(/token/)
expect(subject).not_to include(/variables/) expect(subject).not_to include(/variables/)
......
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