Commit 0ed51041 authored by Nick Thomas's avatar Nick Thomas

Add more attributes to the blob GraphQL API

`ide_edit_path`, `can_modify_blob`, `fork_and_edit_path` and
`ide_fork_and_edit_path` all have implementations in `BlobHelper`,
which are difficult to extract out. For now, just include the required
helpers to get access to the code.

In the future, we should be able to delete the existing FE for viewing
the repository, and at that point we should also be able to move this
code from BlobHelper and into BlobPresenter more easily.

`external_storage_url` has its implementation in `ApplicationHelper`.
Long term, moving this seems less likely. It probably fits better in a
URL generation location like `GitlabRoutingHelpers`, but let's not try
to tackle that as part of this MR.

Changelog: added
parent 6da49550
......@@ -32,6 +32,15 @@ module Types
field :web_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path of the blob.'
field :ide_edit_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path to edit this blob in the Web IDE.'
field :fork_and_edit_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path to edit this blob using a forked project.'
field :ide_fork_and_edit_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path to edit this blob in the Web IDE using a forked project.'
field :size, GraphQL::INT_TYPE, null: true,
description: 'Size (in bytes) of the blob.'
......@@ -53,6 +62,9 @@ module Types
field :raw_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path to download the raw blob.'
field :external_storage_url, GraphQL::STRING_TYPE, null: true,
description: 'Web path to download the raw blob via external storage, if enabled.'
field :replace_path, GraphQL::STRING_TYPE, null: true,
description: 'Web path to replace the blob content.'
......@@ -72,6 +84,10 @@ module Types
null: true,
calls_gitaly: true
field :can_modify_blob, GraphQL::BOOLEAN_TYPE, null: true, method: :can_modify_blob?,
calls_gitaly: true,
description: 'Whether the current user can modify the blob.'
def raw_text_blob
object.data unless object.binary?
end
......
# frozen_string_literal: true
class BlobPresenter < Gitlab::View::Presenter::Delegated
include ApplicationHelper
include BlobHelper
include DiffHelper
include TreeHelper
include ChecksCollaboration
presents :blob
def highlight(to: nil, plain: nil)
......@@ -40,6 +46,28 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
url_helpers.project_create_blob_path(project, ref_qualified_path)
end
def fork_and_edit_path
fork_path_for_current_user(project, edit_blob_path)
end
def ide_fork_and_edit_path
fork_path_for_current_user(project, ide_edit_path)
end
def can_modify_blob?
super(blob, project, blob.commit_id)
end
def ide_edit_path
super(project, blob.commit_id, blob.path)
end
def external_storage_url
return unless static_objects_external_storage_enabled?
external_storage_url_or_path(url_helpers.project_raw_url(project, ref_qualified_path))
end
private
def url_helpers
......
---
title: Add more attributes to the blob GraphQL API
merge_request: 61155
author:
type: added
......@@ -11784,9 +11784,14 @@ Returns [`Tree`](#tree).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="repositoryblobcanmodifyblob"></a>`canModifyBlob` | [`Boolean`](#boolean) | Whether the current user can modify the blob. |
| <a id="repositoryblobeditblobpath"></a>`editBlobPath` | [`String`](#string) | Web path to edit the blob in the old-style editor. |
| <a id="repositoryblobexternalstorageurl"></a>`externalStorageUrl` | [`String`](#string) | Web path to download the raw blob via external storage, if enabled. |
| <a id="repositoryblobfiletype"></a>`fileType` | [`String`](#string) | The expected format of the blob based on the extension. |
| <a id="repositoryblobforkandeditpath"></a>`forkAndEditPath` | [`String`](#string) | Web path to edit this blob using a forked project. |
| <a id="repositoryblobid"></a>`id` | [`ID!`](#id) | ID of the blob. |
| <a id="repositoryblobideeditpath"></a>`ideEditPath` | [`String`](#string) | Web path to edit this blob in the Web IDE. |
| <a id="repositoryblobideforkandeditpath"></a>`ideForkAndEditPath` | [`String`](#string) | Web path to edit this blob in the Web IDE using a forked project. |
| <a id="repositorybloblfsoid"></a>`lfsOid` | [`String`](#string) | LFS OID of the blob. |
| <a id="repositoryblobmode"></a>`mode` | [`String`](#string) | Blob mode. |
| <a id="repositoryblobname"></a>`name` | [`String`](#string) | Blob name. |
......
......@@ -25,7 +25,12 @@ RSpec.describe Types::Repository::BlobType do
:replace_path,
:simple_viewer,
:rich_viewer,
:plain_data
:plain_data,
:can_modify_blob,
:ide_edit_path,
:external_storage_url,
:fork_and_edit_path,
:ide_fork_and_edit_path
)
end
end
......@@ -4,11 +4,12 @@ require 'spec_helper'
RSpec.describe BlobPresenter do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:user) { project.owner }
let(:repository) { project.repository }
let(:blob) { repository.blob_at('HEAD', 'files/ruby/regex.rb') }
subject(:presenter) { described_class.new(blob) }
subject(:presenter) { described_class.new(blob, current_user: user) }
describe '#web_url' do
it { expect(presenter.web_url).to eq("http://localhost/#{project.full_path}/-/blob/#{blob.commit_id}/#{blob.path}") }
......@@ -30,6 +31,42 @@ RSpec.describe BlobPresenter do
it { expect(presenter.replace_path).to eq("/#{project.full_path}/-/create/#{blob.commit_id}/#{blob.path}") }
end
describe '#ide_edit_path' do
it { expect(presenter.ide_edit_path).to eq("/-/ide/project/#{project.full_path}/edit/HEAD/-/files/ruby/regex.rb") }
end
describe '#fork_and_edit_path' do
it 'generates expected URI + query' do
uri = URI.parse(presenter.fork_and_edit_path)
query = Rack::Utils.parse_query(uri.query)
expect(uri.path).to eq("/#{project.full_path}/-/forks")
expect(query).to include('continue[to]' => presenter.edit_blob_path, 'namespace_key' => user.namespace_id.to_s)
end
context 'current_user is nil' do
let(:user) { nil }
it { expect(presenter.fork_and_edit_path).to be_nil }
end
end
describe '#ide_fork_and_edit_path' do
it 'generates expected URI + query' do
uri = URI.parse(presenter.ide_fork_and_edit_path)
query = Rack::Utils.parse_query(uri.query)
expect(uri.path).to eq("/#{project.full_path}/-/forks")
expect(query).to include('continue[to]' => presenter.ide_edit_path, 'namespace_key' => user.namespace_id.to_s)
end
context 'current_user is nil' do
let(:user) { nil }
it { expect(presenter.ide_fork_and_edit_path).to be_nil }
end
end
context 'given a Gitlab::Graphql::Representation::TreeEntry' do
let(:blob) { Gitlab::Graphql::Representation::TreeEntry.new(super(), repository) }
......
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