Commit 2504a8ab authored by Michael Kozono's avatar Michael Kozono

Merge branch 'vue-signature-for-last-commit' into 'master'

Display signature for last commit in tree view

See merge request gitlab-org/gitlab!17288
parents af70f6f9 8b931547
<script> <script>
/* eslint-disable @gitlab/vue-i18n/no-bare-strings */
import { GlTooltipDirective, GlLink, GlButton, GlLoadingIcon } from '@gitlab/ui'; import { GlTooltipDirective, GlLink, GlButton, GlLoadingIcon } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import Icon from '../../vue_shared/components/icon.vue'; import Icon from '../../vue_shared/components/icon.vue';
...@@ -113,7 +112,7 @@ export default { ...@@ -113,7 +112,7 @@ export default {
> >
{{ commit.author.name }} {{ commit.author.name }}
</gl-link> </gl-link>
authored {{ s__('LastCommit|authored') }}
<timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" /> <timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" />
</div> </div>
<pre <pre
...@@ -125,6 +124,7 @@ export default { ...@@ -125,6 +124,7 @@ export default {
</pre> </pre>
</div> </div>
<div class="commit-actions flex-row"> <div class="commit-actions flex-row">
<div v-if="commit.signatureHtml" v-html="commit.signatureHtml"></div>
<gl-link <gl-link
v-if="commit.latestPipeline" v-if="commit.latestPipeline"
v-gl-tooltip v-gl-tooltip
......
...@@ -13,6 +13,7 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) { ...@@ -13,6 +13,7 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
avatarUrl avatarUrl
webUrl webUrl
} }
signatureHtml
latestPipeline { latestPipeline {
detailedStatus { detailedStatus {
detailsPath detailsPath
......
# frozen_string_literal: true
module Resolvers
class LastCommitResolver < BaseResolver
type Types::CommitType, null: true
alias_method :tree, :object
def resolve(**args)
# Ensure merge commits can be returned by sending nil to Gitaly instead of '/'
path = tree.path == '/' ? nil : tree.path
commit = Gitlab::Git::Commit.last_for_path(tree.repository, tree.sha, path)
::Commit.new(commit, tree.repository.project) if commit
end
end
end
...@@ -15,6 +15,8 @@ module Types ...@@ -15,6 +15,8 @@ module Types
field :message, type: GraphQL::STRING_TYPE, null: true # rubocop:disable Graphql/Descriptions field :message, type: GraphQL::STRING_TYPE, null: true # rubocop:disable Graphql/Descriptions
field :authored_date, type: Types::TimeType, null: true # rubocop:disable Graphql/Descriptions field :authored_date, type: Types::TimeType, null: true # rubocop:disable Graphql/Descriptions
field :web_url, type: GraphQL::STRING_TYPE, null: false # rubocop:disable Graphql/Descriptions field :web_url, type: GraphQL::STRING_TYPE, null: false # rubocop:disable Graphql/Descriptions
field :signature_html, type: GraphQL::STRING_TYPE,
null: true, calls_gitaly: true, description: 'Rendered html for the commit signature'
# models/commit lazy loads the author by email # models/commit lazy loads the author by email
field :author, type: Types::UserType, null: true # rubocop:disable Graphql/Descriptions field :author, type: Types::UserType, null: true # rubocop:disable Graphql/Descriptions
......
...@@ -7,9 +7,9 @@ module Types ...@@ -7,9 +7,9 @@ module Types
graphql_name 'Tree' graphql_name 'Tree'
# Complexity 10 as it triggers a Gitaly call on each render # Complexity 10 as it triggers a Gitaly call on each render
field :last_commit, Types::CommitType, null: true, complexity: 10, calls_gitaly: true, resolve: -> (tree, args, ctx) do # rubocop:disable Graphql/Descriptions field :last_commit, Types::CommitType,
tree.repository.last_commit_for_path(tree.sha, tree.path) null: true, complexity: 10, calls_gitaly: true, resolver: Resolvers::LastCommitResolver,
end description: 'Last commit for the tree'
field :trees, Types::Tree::TreeEntryType.connection_type, null: false, resolve: -> (obj, args, ctx) do # rubocop:disable Graphql/Descriptions field :trees, Types::Tree::TreeEntryType.connection_type, null: false, resolve: -> (obj, args, ctx) do # rubocop:disable Graphql/Descriptions
Gitlab::Graphql::Representation::TreeEntry.decorate(obj.trees, obj.repository) Gitlab::Graphql::Representation::TreeEntry.decorate(obj.trees, obj.repository)
......
...@@ -20,4 +20,15 @@ class CommitPresenter < Gitlab::View::Presenter::Delegated ...@@ -20,4 +20,15 @@ class CommitPresenter < Gitlab::View::Presenter::Delegated
def web_url def web_url
Gitlab::UrlBuilder.new(commit).url Gitlab::UrlBuilder.new(commit).url
end end
def signature_html
return unless commit.has_signature?
ApplicationController.renderer.render(
'projects/commit/_signature',
locals: { signature: commit.signature },
layout: false,
formats: [:html]
)
end
end end
...@@ -9224,6 +9224,9 @@ msgstr "" ...@@ -9224,6 +9224,9 @@ msgstr ""
msgid "Last used on:" msgid "Last used on:"
msgstr "" msgstr ""
msgid "LastCommit|authored"
msgstr ""
msgid "LastPushEvent|You pushed to" msgid "LastPushEvent|You pushed to"
msgstr "" msgstr ""
......
...@@ -60,6 +60,111 @@ exports[`Repository last commit component renders commit widget 1`] = ` ...@@ -60,6 +60,111 @@ exports[`Repository last commit component renders commit widget 1`] = `
<div <div
class="commit-actions flex-row" 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>
`;
exports[`Repository last commit component renders the signature HTML as returned by the backend 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"
>
<div>
<button>
Verified
</button>
</div>
<gllink-stub <gllink-stub
class="js-commit-pipeline" class="js-commit-pipeline"
data-original-title="Commit: failed" data-original-title="Commit: failed"
......
...@@ -107,4 +107,10 @@ describe('Repository last commit component', () => { ...@@ -107,4 +107,10 @@ describe('Repository last commit component', () => {
expect(vm.find('.commit-row-description').isVisible()).toBe(true); expect(vm.find('.commit-row-description').isVisible()).toBe(true);
expect(vm.find('.text-expander').classes('open')).toBe(true); expect(vm.find('.text-expander').classes('open')).toBe(true);
}); });
it('renders the signature HTML as returned by the backend', () => {
factory(createCommitData({ signatureHtml: '<button>Verified</button>' }));
expect(vm.element).toMatchSnapshot();
});
}); });
# frozen_string_literal: true
require 'spec_helper'
describe Resolvers::LastCommitResolver do
include GraphqlHelpers
let(:repository) { create(:project, :repository).repository }
let(:tree) { repository.tree(ref, path) }
let(:commit) { resolve(described_class, obj: tree) }
describe '#resolve' do
context 'last commit is a merge commit' do
let(:ref) { 'master' }
let(:path) { '/' }
it 'resolves to the merge commit' do
expect(commit).to eq(repository.commits(ref, limit: 1).last)
end
end
context 'last commit for a different branch and path' do
let(:ref) { 'fix' }
let(:path) { 'files' }
it 'resolves commit' do
expect(commit).to eq(repository.commits(ref, path: path, limit: 1).last)
end
end
context 'last commit does not exist' do
let(:ref) { 'master' }
let(:path) { 'does-not-exist' }
it 'returns nil' do
expect(commit).to be_nil
end
end
end
end
...@@ -7,5 +7,10 @@ describe GitlabSchema.types['Commit'] do ...@@ -7,5 +7,10 @@ describe GitlabSchema.types['Commit'] do
it { expect(described_class).to require_graphql_authorizations(:download_code) } it { expect(described_class).to require_graphql_authorizations(:download_code) }
it { expect(described_class).to have_graphql_fields(:id, :sha, :title, :description, :message, :authored_date, :author, :web_url, :latest_pipeline) } it 'contains attributes related to commit' do
expect(described_class).to have_graphql_fields(
:id, :sha, :title, :description, :message, :authored_date,
:author, :web_url, :latest_pipeline, :signature_html
)
end
end end
...@@ -55,4 +55,17 @@ describe CommitPresenter do ...@@ -55,4 +55,17 @@ describe CommitPresenter do
end end
end end
end end
describe '#signature_html' do
let(:signature) { 'signature' }
before do
expect(commit).to receive(:has_signature?).and_return(true)
allow(ApplicationController.renderer).to receive(:render).and_return(signature)
end
it 'renders html for displaying signature' do
expect(presenter.signature_html).to eq(signature)
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