Commit bf6b7066 authored by Phil Hughes's avatar Phil Hughes

Render tree last commit widget with Vue

Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/62766
parent 8716eb0c
<script>
import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale';
import Icon from '../../vue_shared/components/icon.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
import CommitPipelineStatus from '../../projects/tree/components/commit_pipeline_status_component.vue';
import CiIcon from '../../vue_shared/components/ci_icon.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import getRefMixin from '../mixins/get_ref';
import getProjectPath from '../queries/getProjectPath.graphql';
import pathLastCommit from '../queries/pathLastCommit.query.graphql';
export default {
components: {
Icon,
UserAvatarLink,
TimeagoTooltip,
CommitPipelineStatus,
ClipboardButton,
CiIcon,
GlLink,
GlButton,
},
directives: {
GlTooltip: GlTooltipDirective,
},
mixins: [getRefMixin],
apollo: {
projectPath: {
query: getProjectPath,
},
commit: {
query: pathLastCommit,
variables() {
return {
projectPath: this.projectPath,
ref: this.ref,
path: this.currentPath.replace(/^\//, ''),
};
},
update: data => data.project.repository.tree.commit,
},
},
props: {
currentPath: {
type: String,
required: false,
default: '',
},
},
data() {
return {
projectPath: '',
commit: {},
showDescription: false,
};
},
computed: {
statusTitle() {
return sprintf(s__('Commits|Commit: %{commitText}'), {
commitText: this.commit.pipeline.detailedStatus.text,
});
},
isLoading() {
return this.$apollo.queries.commit.loading;
},
showCommitId() {
return this.commit.id.substr(0, 8);
},
},
methods: {
toggleShowDescription() {
this.showDescription = !this.showDescription;
},
},
};
</script>
<template>
<div v-if="!isLoading" class="info-well d-none d-sm-flex project-last-commit commit p-3">
<user-avatar-link
v-if="commit.author"
:link-href="commit.author.webUrl"
:img-src="commit.author.avatarUrl"
:img-size="40"
class="avatar-cell"
/>
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<gl-link :href="commit.webUrl" class="commit-row-message item-title">
{{ commit.title }}
</gl-link>
<gl-button
v-if="commit.description"
:class="{ open: showDescription }"
:aria-label="__('Show commit description')"
class="text-expander"
@click="toggleShowDescription"
>
<icon name="ellipsis_h" />
</gl-button>
<div class="committer">
<gl-link
v-if="commit.author"
:href="commit.author.webUrl"
class="commit-author-link js-user-link"
>
{{ commit.author.name }}
</gl-link>
authored
<timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" />
</div>
<pre
v-if="commit.description"
v-show="showDescription"
class="commit-row-description append-bottom-8"
>
{{ commit.description }}
</pre>
</div>
<div class="commit-actions flex-row">
<gl-link
v-if="commit.pipeline"
v-gl-tooltip
:href="commit.pipeline.detailedStatus.detailsPath"
:title="statusTitle"
class="js-commit-pipeline"
>
<ci-icon :status="commit.pipeline.detailedStatus" :size="24" :aria-label="statusTitle" />
</gl-link>
<div class="commit-sha-group d-flex">
<div class="label label-monospace monospace">
{{ showCommitId }}
</div>
<clipboard-button
:text="commit.id"
:title="__('Copy commit SHA to clipboard')"
tooltip-placement="bottom"
/>
</div>
</div>
</div>
</div>
</template>
...@@ -2,6 +2,7 @@ import Vue from 'vue'; ...@@ -2,6 +2,7 @@ import Vue from 'vue';
import createRouter from './router'; import createRouter from './router';
import App from './components/app.vue'; import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue'; import Breadcrumbs from './components/breadcrumbs.vue';
import LastCommit from './components/last_commit.vue';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
import { setTitle } from './utils/title'; import { setTitle } from './utils/title';
...@@ -48,6 +49,24 @@ export default function setupVueRepositoryList() { ...@@ -48,6 +49,24 @@ export default function setupVueRepositoryList() {
}, },
}); });
const commitEl = document.getElementById('js-last-commit');
if (commitEl) {
// eslint-disable-next-line no-new
new Vue({
el: commitEl,
router,
apolloProvider,
render(h) {
return h(LastCommit, {
props: {
currentPath: this.$route.params.pathMatch,
},
});
},
});
}
return new Vue({ return new Vue({
el, el,
router, router,
......
query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
project(fullPath: $projectPath) {
repository {
tree(path: $path, ref: $ref) {
commit {
id
title
message
webUrl
authoredDate
author {
name
avatarUrl
webUrl
}
pipeline {
detailedStatus {
detailsPath
icon
tooltip
text
group
}
}
}
}
}
}
}
...@@ -9140,6 +9140,9 @@ msgstr "" ...@@ -9140,6 +9140,9 @@ msgstr ""
msgid "Show comments only" msgid "Show comments only"
msgstr "" msgstr ""
msgid "Show commit description"
msgstr ""
msgid "Show complete raw log" msgid "Show complete raw log"
msgstr "" msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Repository last commit component renders commit widget 1`] = `
<div
class="info-well d-none d-sm-flex project-last-commit commit p-3"
>
<useravatarlink-stub
class="avatar-cell"
imgalt=""
imgcssclasses=""
imgsize="40"
imgsrc="https://test.com"
linkhref="https://test.com/test"
tooltipplacement="top"
tooltiptext=""
username=""
/>
<div
class="commit-detail flex-list"
>
<div
class="commit-content qa-commit-content"
>
<gllink-stub
class="commit-row-message item-title"
href="https://test.com/commit/123"
>
Commit title
</gllink-stub>
<!---->
<div
class="committer"
>
<gllink-stub
class="commit-author-link js-user-link"
href="https://test.com/test"
>
Test
</gllink-stub>
authored
<timeagotooltip-stub
cssclass=""
time="2019-01-01"
tooltipplacement="bottom"
/>
</div>
<!---->
</div>
<div
class="commit-actions flex-row"
>
<gllink-stub
class="js-commit-pipeline"
data-original-title="Commit: failed"
href="https://test.com/pipeline"
title=""
>
<ciicon-stub
aria-label="Commit: failed"
cssclasses=""
size="24"
status="[object Object]"
/>
</gllink-stub>
<div
class="commit-sha-group d-flex"
>
<div
class="label label-monospace monospace"
>
12345678
</div>
<clipboardbutton-stub
cssclass="btn-default"
text="123456789"
title="Copy commit SHA to clipboard"
tooltipplacement="bottom"
/>
</div>
</div>
</div>
</div>
`;
import { shallowMount } from '@vue/test-utils';
import LastCommit from '~/repository/components/last_commit.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
let vm;
function createCommitData(data = {}) {
return {
id: '123456789',
title: 'Commit title',
message: 'Commit message',
webUrl: 'https://test.com/commit/123',
authoredDate: '2019-01-01',
author: {
name: 'Test',
avatarUrl: 'https://test.com',
webUrl: 'https://test.com/test',
},
pipeline: {
detailedStatus: {
detailsPath: 'https://test.com/pipeline',
icon: 'failed',
tooltip: 'failed',
text: 'failed',
group: {},
},
},
...data,
};
}
function factory(commit = createCommitData(), loading = false) {
vm = shallowMount(LastCommit, {
mocks: {
$apollo: {
queries: {
commit: {
loading: true,
},
},
},
},
});
vm.setData({ commit });
vm.vm.$apollo.queries.commit.loading = loading;
}
describe('Repository last commit component', () => {
afterEach(() => {
vm.destroy();
});
it.each`
loading | label
${true} | ${'hides'}
${false} | ${'shows'}
`('$label when $loading is true', ({ loading }) => {
factory(createCommitData(), loading);
expect(vm.isEmpty()).toBe(loading);
});
it('renders commit widget', () => {
factory();
expect(vm.element).toMatchSnapshot();
});
it('renders short commit ID', () => {
factory();
expect(vm.find('.label-monospace').text()).toEqual('12345678');
});
it('hides pipeline components when pipeline does not exist', () => {
factory(createCommitData({ pipeline: null }));
expect(vm.find('.js-commit-pipeline').exists()).toBe(false);
});
it('hides author component when author does not exist', () => {
factory(createCommitData({ author: null }));
expect(vm.find('.js-user-link').exists()).toBe(false);
expect(vm.find(UserAvatarLink).exists()).toBe(false);
});
it('does not render description expander when description is null', () => {
factory(createCommitData({ description: null }));
expect(vm.find('.text-expander').exists()).toBe(false);
expect(vm.find('.commit-row-description').exists()).toBe(false);
});
it('expands commit description when clicking expander', () => {
factory(createCommitData({ description: 'Test description' }));
vm.find('.text-expander').vm.$emit('click');
expect(vm.find('.commit-row-description').isVisible()).toBe(true);
expect(vm.find('.text-expander').classes('open')).toBe(true);
});
});
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