Merge branch 'dm-snippet-download-button' into 'master'

Add download button to project snippets

See merge request !11004
This commit is contained in:
Sean McGivern 2017-05-02 15:25:26 +00:00
commit c5dee301f8
11 changed files with 166 additions and 144 deletions

View file

@ -5,10 +5,12 @@ module SnippetsActions
end end
def raw def raw
disposition = params[:inline] == 'false' ? 'attachment' : 'inline'
send_data( send_data(
convert_line_endings(@snippet.content), convert_line_endings(@snippet.content),
type: 'text/plain; charset=utf-8', type: 'text/plain; charset=utf-8',
disposition: 'inline', disposition: disposition,
filename: @snippet.sanitized_file_name filename: @snippet.sanitized_file_name
) )
end end

View file

@ -6,10 +6,10 @@ class SnippetsController < ApplicationController
include MarkdownPreview include MarkdownPreview
include RendersBlob include RendersBlob
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw, :download] before_action :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read snippet # Allow read snippet
before_action :authorize_read_snippet!, only: [:show, :raw, :download] before_action :authorize_read_snippet!, only: [:show, :raw]
# Allow modify snippet # Allow modify snippet
before_action :authorize_update_snippet!, only: [:edit, :update] before_action :authorize_update_snippet!, only: [:edit, :update]
@ -17,7 +17,7 @@ class SnippetsController < ApplicationController
# Allow destroy snippet # Allow destroy snippet
before_action :authorize_admin_snippet!, only: [:destroy] before_action :authorize_admin_snippet!, only: [:destroy]
skip_before_action :authenticate_user!, only: [:index, :show, :raw, :download] skip_before_action :authenticate_user!, only: [:index, :show, :raw]
layout 'snippets' layout 'snippets'
respond_to :html respond_to :html
@ -89,14 +89,6 @@ class SnippetsController < ApplicationController
redirect_to snippets_path redirect_to snippets_path
end end
def download
send_data(
convert_line_endings(@snippet.content),
type: 'text/plain; charset=utf-8',
filename: @snippet.sanitized_file_name
)
end
def preview_markdown def preview_markdown
render_markdown_preview(params[:text], skip_project_check: true) render_markdown_preview(params[:text], skip_project_check: true)
end end

View file

@ -8,6 +8,14 @@ module SnippetsHelper
end end
end end
def download_snippet_path(snippet)
if snippet.project_id
raw_namespace_project_snippet_path(@project.namespace, @project, snippet, inline: false)
else
raw_snippet_path(snippet, inline: false)
end
end
# Return the path of a snippets index for a user or for a project # Return the path of a snippets index for a user or for a project
# #
# @returns String, path to snippet index # @returns String, path to snippet index

View file

@ -18,7 +18,6 @@
= copy_blob_source_button(blob) = copy_blob_source_button(blob)
= open_raw_blob_button(blob) = open_raw_blob_button(blob)
- if defined?(download_path) && download_path = link_to icon('download'), download_snippet_path(@snippet), target: '_blank', class: "btn btn-sm has-tooltip", title: 'Download', data: { container: 'body' }
= link_to icon('download'), download_path, class: "btn btn-sm has-tooltip", title: 'Download', data: { container: 'body' }
= render 'projects/blob/content', blob: blob = render 'projects/blob/content', blob: blob

View file

@ -3,7 +3,7 @@
= render 'shared/snippets/header' = render 'shared/snippets/header'
%article.file-holder.snippet-file-content %article.file-holder.snippet-file-content
= render 'shared/snippets/blob', download_path: download_snippet_path(@snippet) = render 'shared/snippets/blob'
.row-content-block.top-block.content-component-block .row-content-block.top-block.content-component-block
= render 'award_emoji/awards_block', awardable: @snippet, inline: true = render 'award_emoji/awards_block', awardable: @snippet, inline: true

View file

@ -0,0 +1,4 @@
---
title: Add download button to project snippets
merge_request:
author:

View file

@ -44,7 +44,7 @@ constraints(ProjectUrlConstrainer.new) do
resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do resources :snippets, concerns: :awardable, constraints: { id: /\d+/ } do
member do member do
get 'raw' get :raw
post :mark_as_spam post :mark_as_spam
end end
end end

View file

@ -1,7 +1,6 @@
resources :snippets, concerns: :awardable do resources :snippets, concerns: :awardable do
member do member do
get 'raw' get :raw
get 'download'
post :mark_as_spam post :mark_as_spam
post :preview_markdown post :preview_markdown
end end

View file

@ -350,8 +350,7 @@ describe SnippetsController do
end end
end end
%w(raw download).each do |action| describe "GET #raw" do
describe "GET #{action}" do
context 'when the personal snippet is private' do context 'when the personal snippet is private' do
let(:personal_snippet) { create(:personal_snippet, :private, author: user) } let(:personal_snippet) { create(:personal_snippet, :private, author: user) }
@ -365,14 +364,14 @@ describe SnippetsController do
let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) } let(:other_personal_snippet) { create(:personal_snippet, :private, author: other_author) }
it 'responds with status 404' do it 'responds with status 404' do
get action, id: other_personal_snippet.to_param get :raw, id: other_personal_snippet.to_param
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
context 'when signed in user is the author' do context 'when signed in user is the author' do
before { get action, id: personal_snippet.to_param } before { get :raw, id: personal_snippet.to_param }
it 'responds with status 200' do it 'responds with status 200' do
expect(assigns(:snippet)).to eq(personal_snippet) expect(assigns(:snippet)).to eq(personal_snippet)
@ -382,18 +381,14 @@ describe SnippetsController do
it 'has expected headers' do it 'has expected headers' do
expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8') expect(response.header['Content-Type']).to eq('text/plain; charset=utf-8')
if action == :download
expect(response.header['Content-Disposition']).to match(/attachment/)
elsif action == :raw
expect(response.header['Content-Disposition']).to match(/inline/) expect(response.header['Content-Disposition']).to match(/inline/)
end end
end end
end end
end
context 'when not signed in' do context 'when not signed in' do
it 'redirects to the sign in page' do it 'redirects to the sign in page' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path) expect(response).to redirect_to(new_user_session_path)
end end
@ -409,7 +404,7 @@ describe SnippetsController do
end end
it 'responds with status 200' do it 'responds with status 200' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet) expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
@ -418,7 +413,7 @@ describe SnippetsController do
context 'when not signed in' do context 'when not signed in' do
it 'redirects to the sign in page' do it 'redirects to the sign in page' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(response).to redirect_to(new_user_session_path) expect(response).to redirect_to(new_user_session_path)
end end
@ -434,7 +429,7 @@ describe SnippetsController do
end end
it 'responds with status 200' do it 'responds with status 200' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet) expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
@ -446,13 +441,13 @@ describe SnippetsController do
end end
it 'returns LF line endings by default' do it 'returns LF line endings by default' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(response.body).to eq("first line\nsecond line\nthird line") expect(response.body).to eq("first line\nsecond line\nthird line")
end end
it 'does not convert line endings when parameter present' do it 'does not convert line endings when parameter present' do
get action, id: personal_snippet.to_param, line_ending: :raw get :raw, id: personal_snippet.to_param, line_ending: :raw
expect(response.body).to eq("first line\r\nsecond line\r\nthird line") expect(response.body).to eq("first line\r\nsecond line\r\nthird line")
end end
@ -461,7 +456,7 @@ describe SnippetsController do
context 'when not signed in' do context 'when not signed in' do
it 'responds with status 200' do it 'responds with status 200' do
get action, id: personal_snippet.to_param get :raw, id: personal_snippet.to_param
expect(assigns(:snippet)).to eq(personal_snippet) expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
@ -476,7 +471,7 @@ describe SnippetsController do
end end
it 'responds with status 404' do it 'responds with status 404' do
get action, id: 'doesntexist' get :raw, id: 'doesntexist'
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
@ -484,14 +479,13 @@ describe SnippetsController do
context 'when not signed in' do context 'when not signed in' do
it 'responds with status 404' do it 'responds with status 404' do
get action, id: 'doesntexist' get :raw, id: 'doesntexist'
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
end end
end end
end end
end end
end
context 'award emoji on snippets' do context 'award emoji on snippets' do
let(:personal_snippet) { create(:personal_snippet, :public, author: user) } let(:personal_snippet) { create(:personal_snippet, :public, author: user) }

View file

@ -30,6 +30,12 @@ feature 'Project snippet', :js, feature: true do
# shows an enabled copy button # shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
# shows a download button
expect(page).to have_link('Download')
end end
end end
end end
@ -59,6 +65,12 @@ feature 'Project snippet', :js, feature: true do
# shows a disabled copy button # shows a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled') expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
# shows a raw button
expect(page).to have_link('Open raw')
# shows a download button
expect(page).to have_link('Download')
end end
end end

View file

@ -24,6 +24,12 @@ feature 'Snippet', :js, feature: true do
# shows an enabled copy button # shows an enabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)') expect(page).to have_selector('.js-copy-blob-source-btn:not(.disabled)')
# shows a raw button
expect(page).to have_link('Open raw')
# shows a download button
expect(page).to have_link('Download')
end end
end end
end end
@ -53,6 +59,12 @@ feature 'Snippet', :js, feature: true do
# shows a disabled copy button # shows a disabled copy button
expect(page).to have_selector('.js-copy-blob-source-btn.disabled') expect(page).to have_selector('.js-copy-blob-source-btn.disabled')
# shows a raw button
expect(page).to have_link('Open raw')
# shows a download button
expect(page).to have_link('Download')
end end
end end