summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--app/assets/javascripts/blob/blob_file_dropzone.js.coffee52
-rw-r--r--app/assets/stylesheets/generic/blocks.scss7
-rw-r--r--app/assets/stylesheets/generic/common.scss4
-rw-r--r--app/assets/stylesheets/pages/editor.scss18
-rw-r--r--app/assets/stylesheets/pages/tree.scss12
-rw-r--r--app/controllers/projects/blob_controller.rb28
-rw-r--r--app/helpers/gitlab_routing_helper.rb8
-rw-r--r--app/helpers/projects_helper.rb71
-rw-r--r--app/services/files/create_service.rb2
-rw-r--r--app/views/events/_event_last_push.html.haml24
-rw-r--r--app/views/groups/edit.html.haml2
-rw-r--r--app/views/groups/projects.html.haml2
-rw-r--r--app/views/layouts/nav/_project.html.haml8
-rw-r--r--app/views/layouts/project.html.haml2
-rw-r--r--app/views/projects/_last_push.html.haml23
-rw-r--r--app/views/projects/blob/_actions.html.haml6
-rw-r--r--app/views/projects/blob/_replace.html.haml28
-rw-r--r--app/views/projects/blob/_upload.html.haml28
-rw-r--r--app/views/projects/blob/edit.html.haml2
-rw-r--r--app/views/projects/blob/new.html.haml10
-rw-r--r--app/views/projects/blob/show.html.haml1
-rw-r--r--app/views/projects/commits/_head.html.haml4
-rw-r--r--app/views/projects/labels/index.html.haml15
-rw-r--r--app/views/projects/project_members/index.html.haml42
-rw-r--r--app/views/projects/show.html.haml2
-rw-r--r--app/views/users/show.html.haml4
-rw-r--r--config/routes.rb10
-rw-r--r--features/project/source/browse_files.feature23
-rw-r--r--features/steps/project/source/browse_files.rb83
30 files changed, 427 insertions, 95 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 84f9688c3a8..007e47f7446 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -3,6 +3,7 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.0.0 (unreleased)
- Bump rouge to 1.10.1 to remove warning noise and fix other syntax highlighting bugs (Stan Hu)
- Gracefully handle errors in syntax highlighting by leaving the block unformatted (Stan Hu)
+ - Add "replace" and "upload" functionalities to allow user replace existing file and upload new file into current repository
- Fix URL construction for merge requests, issues, notes, and commits for relative URL config (Stan Hu)
- Fix emoji URLs in Markdown when relative_url_root is used (Stan Hu)
- Omit filename in Content-Disposition header in raw file download to avoid RFC 6266 encoding issues (Stan HU)
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js.coffee b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
new file mode 100644
index 00000000000..090af9bb376
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js.coffee
@@ -0,0 +1,52 @@
+class @BlobFileDropzone
+ constructor: (form, method) ->
+ form_dropzone = form.find('.dropzone')
+ Dropzone.autoDiscover = false
+ dropzone = form_dropzone.dropzone(
+ autoDiscover: false
+ autoProcessQueue: false
+ url: form.attr('action')
+ # Rails uses a hidden input field for PUT
+ # http://stackoverflow.com/questions/21056482/how-to-set-method-put-in-form-tag-in-rails
+ method: method
+ clickable: true
+ uploadMultiple: false
+ paramName: "file"
+ maxFilesize: gon.max_file_size or 10
+ parallelUploads: 1
+ maxFiles: 1
+ addRemoveLinks: true
+ previewsContainer: '.dropzone-previews'
+ headers:
+ "X-CSRF-Token": $("meta[name=\"csrf-token\"]").attr("content")
+
+ success: (header, response) ->
+ window.location.href = response.filePath
+ return
+
+ error: (temp, errorMessage) ->
+ stripped = $("<div/>").html(errorMessage).text();
+ $('.dropzone-alerts').html('Error uploading file: \"' + stripped + '\"').show()
+ return
+
+ maxfilesexceeded: (file) ->
+ @removeFile file
+ return
+
+ removedfile: (file) ->
+ $('.dropzone-previews')[0].removeChild(file.previewTemplate)
+ $('.dropzone-alerts').html('').hide()
+ return true
+
+ sending: (file, xhr, formData) ->
+ formData.append('commit_message', form.find('#commit_message').val())
+ return
+ )
+
+ submitButton = form.find('#submit-all')[0]
+ submitButton.addEventListener 'click', (e) ->
+ e.preventDefault()
+ e.stopPropagation()
+ alert "Please select a file" if dropzone[0].dropzone.getQueuedFiles().length == 0
+ dropzone[0].dropzone.processQueue()
+ return false
diff --git a/app/assets/stylesheets/generic/blocks.scss b/app/assets/stylesheets/generic/blocks.scss
index 48d9f890f62..ce024272a30 100644
--- a/app/assets/stylesheets/generic/blocks.scss
+++ b/app/assets/stylesheets/generic/blocks.scss
@@ -36,6 +36,11 @@
margin-bottom: 0;
}
+ &.clear-block {
+ margin-bottom: $gl-padding - 1px;
+ padding-bottom: $gl-padding;
+ }
+
&.second-block {
margin-top: -1px;
margin-bottom: 0;
@@ -51,6 +56,6 @@
}
.oneline {
- line-height: 44px;
+ line-height: 42px;
}
}
diff --git a/app/assets/stylesheets/generic/common.scss b/app/assets/stylesheets/generic/common.scss
index 5e191d5dd4a..3a237bf3228 100644
--- a/app/assets/stylesheets/generic/common.scss
+++ b/app/assets/stylesheets/generic/common.scss
@@ -377,4 +377,8 @@ table {
height: 56px;
margin-top: -$gl-padding;
padding-top: $gl-padding;
+
+ &.no-bottom {
+ margin-bottom: 0;
+ }
}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 759ba6b1c22..1d565477dd4 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -9,6 +9,10 @@
width: 100%;
}
+ .ace_gutter-cell {
+ background-color: $background-color;
+ }
+
.cancel-btn {
color: #B94A48;
&:hover {
@@ -32,14 +36,12 @@
.file-title {
@extend .monospace;
- font-size: 14px;
- padding: 5px;
}
.editor-ref {
background: $background-color;
padding: 11px 15px;
- border-right: 1px solid #CCC;
+ border-right: 1px solid $border-color;
display: inline-block;
margin: -5px -5px;
margin-right: 10px;
@@ -50,5 +52,15 @@
display: inline-block;
width: 200px;
}
+
+ .form-control {
+ margin-top: -3px;
+ }
+ }
+
+ .form-actions {
+ margin: -$gl-padding;
+ margin-top: 0;
+ padding: $gl-padding
}
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index 71ca37c0cd7..df7fab07a57 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -116,3 +116,15 @@
}
#modal-remove-blob > .modal-dialog { width: 850px; }
+
+.blob-upload-dropzone-previews {
+ text-align: center;
+ border: 2px;
+ border-style: dashed;
+ min-height: 200px;
+}
+
+.upload-link {
+ font-weight: normal;
+ color: #0000EE;
+}
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 100d3d3b317..8776721d243 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -26,10 +26,16 @@ class Projects::BlobController < Projects::ApplicationController
if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed"
- redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path))
+ respond_to do |format|
+ format.html { redirect_to namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) }
+ format.json { render json: { message: "success", filePath: namespace_project_blob_path(@project.namespace, @project, File.join(@target_branch, @file_path)) } }
+ end
else
flash[:alert] = result[:message]
- render :new
+ respond_to do |format|
+ format.html { render :new }
+ format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } }
+ end
end
end
@@ -45,10 +51,16 @@ class Projects::BlobController < Projects::ApplicationController
if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed"
- redirect_to after_edit_path
+ respond_to do |format|
+ format.html { redirect_to after_edit_path }
+ format.json { render json: { message: "success", filePath: after_edit_path } }
+ end
else
flash[:alert] = result[:message]
- render :edit
+ respond_to do |format|
+ format.html { render :edit }
+ format.json { render json: { message: "failed", filePath: namespace_project_new_blob_path(@project.namespace, @project, @id) } }
+ end
end
end
@@ -146,11 +158,19 @@ class Projects::BlobController < Projects::ApplicationController
@file_path =
if action_name.to_s == 'create'
+ if params[:file].present?
+ params[:file_name] = params[:file].original_filename
+ end
File.join(@path, File.basename(params[:file_name]))
else
@path
end
+ if params[:file].present?
+ params[:content] = Base64.encode64(params[:file].read)
+ params[:encoding] = 'base64'
+ end
+
@commit_params = {
file_path: @file_path,
current_branch: @current_branch,
diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb
index d0fae255a04..e0816f4e714 100644
--- a/app/helpers/gitlab_routing_helper.rb
+++ b/app/helpers/gitlab_routing_helper.rb
@@ -17,6 +17,14 @@ module GitlabRoutingHelper
namespace_project_path(project.namespace, project, *args)
end
+ def project_files_path(project, *args)
+ namespace_project_tree_path(project.namespace, project, @ref || project.repository.root_ref)
+ end
+
+ def project_commits_path(project, *args)
+ namespace_project_commits_path(project.namespace, project, @ref || project.repository.root_ref)
+ end
+
def activity_project_path(project, *args)
activity_namespace_project_path(project.namespace, project, *args)
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index ab9b068de05..6a2de0de77c 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -43,24 +43,22 @@ module ProjectsHelper
end
end
- def project_title(project)
- if project.group
- content_tag :span do
- link_to(
- simple_sanitize(project.group.name), group_path(project.group)
- ) + ' / ' +
- link_to(simple_sanitize(project.name),
- project_path(project))
- end
- else
- owner = project.namespace.owner
- content_tag :span do
- link_to(
- simple_sanitize(owner.name), user_path(owner)
- ) + ' / ' +
- link_to(simple_sanitize(project.name),
- project_path(project))
+ def project_title(project, name = nil, url = nil)
+ namespace_link =
+ if project.group
+ link_to(simple_sanitize(project.group.name), group_path(project.group))
+ else
+ owner = project.namespace.owner
+ link_to(simple_sanitize(owner.name), user_path(owner))
end
+
+ project_link = link_to(simple_sanitize(project.name), project_path(project))
+
+ full_title = namespace_link + ' / ' + project_link
+ full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name
+
+ content_tag :span do
+ full_title
end
end
@@ -315,6 +313,45 @@ module ProjectsHelper
end
end
+ def current_ref
+ @ref || @repository.try(:root_ref)
+ end
+
+ def detect_project_title(project)
+ name, url =
+ if current_controller? 'wikis'
+ ['Wiki', get_project_wiki_path(project)]
+ elsif current_controller? 'project_members'
+ ['Members', namespace_project_project_members_path(project.namespace, project)]
+ elsif current_controller? 'labels'
+ ['Labels', namespace_project_labels_path(project.namespace, project)]
+ elsif current_controller? 'members'
+ ['Members', project_files_path(project)]
+ elsif current_controller? 'commits'
+ ['Commits', project_commits_path(project)]
+ elsif current_controller? 'graphs'
+ ['Graphs', namespace_project_graph_path(project.namespace, project, current_ref)]
+ elsif current_controller? 'network'
+ ['Network', namespace_project_network_path(project.namespace, project, current_ref)]
+ elsif current_controller? 'milestones'
+ ['Milestones', namespace_project_milestones_path(project.namespace, project)]
+ elsif current_controller? 'snippets'
+ ['Snippets', namespace_project_snippets_path(project.namespace, project)]
+ elsif current_controller? 'issues'
+ ['Issues', namespace_project_issues_path(project.namespace, project)]
+ elsif current_controller? 'merge_requests'
+ ['Merge Requests', namespace_project_merge_requests_path(project.namespace, project)]
+ elsif current_controller? 'tree', 'blob'
+ ['Files', project_files_path(project)]
+ elsif current_path? 'projects#activity'
+ ['Activity', activity_project_path(project)]
+ else
+ [nil, nil]
+ end
+
+ project_title(project, name, url)
+ end
+
private
def filename_path(project, filename)
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index c2da0c30bad..ffbb5993279 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -19,6 +19,8 @@ module Files
end
unless project.empty_repo?
+ @file_path.slice!(0) if @file_path.start_with?('/')
+
blob = repository.blob_at_branch(@current_branch, @file_path)
if blob
diff --git a/app/views/events/_event_last_push.html.haml b/app/views/events/_event_last_push.html.haml
index 6a0c6cba41b..ffc37ad6178 100644
--- a/app/views/events/_event_last_push.html.haml
+++ b/app/views/events/_event_last_push.html.haml
@@ -1,14 +1,14 @@
- if show_last_push_widget?(event)
- .event-last-push
- .event-last-push-text
- %span You pushed to
- = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
- %strong= event.ref_name
- %span at
- %strong= link_to_project event.project
- #{time_ago_with_tooltip(event.created_at)}
+ .gray-content-block.clear-block
+ .event-last-push
+ .event-last-push-text
+ %span You pushed to
+ = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
+ %strong= event.ref_name
+ %span at
+ %strong= link_to_project event.project
+ #{time_ago_with_tooltip(event.created_at)}
- .pull-right
- = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do
- Create Merge Request
- %hr
+ .pull-right
+ = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do
+ Create Merge Request
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index ac7d9ba0f4f..ae8fc9f85f0 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,4 +1,6 @@
+- header_title group_title(@group, "Settings", edit_group_path(@group))
- @blank_container = true
+
.panel.panel-default
.panel-heading
%strong= @group.name
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index d06cfa7ff9f..f1d507a50c7 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -1,4 +1,6 @@
- page_title "Projects"
+- header_title group_title(@group, "Projects", projects_group_path(@group))
+
.panel.panel-default
.panel-heading
%strong= @group.name
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 1d22a7442e3..8ce46d4865b 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -26,28 +26,28 @@
Activity
- if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
- = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do
+ = link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do
= icon('files-o fw')
%span
Files
- if project_nav_tab? :commits
= nav_link(controller: %w(commit commits compare repositories tags branches)) do
- = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
+ = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
= icon('history fw')
%span
Commits
- if project_nav_tab? :network
= nav_link(controller: %w(network)) do
- = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do
+ = link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do
= icon('code-fork fw')
%span
Network
- if project_nav_tab? :graphs
= nav_link(controller: %w(graphs)) do
- = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do
+ = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do
= icon('area-chart fw')
%span
Graphs
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 44afa33dfe5..5c4dd67f0ec 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -1,5 +1,5 @@
- page_title @project.name_with_namespace
-- header_title project_title(@project)
+- header_title detect_project_title(@project)
- sidebar "project" unless sidebar
- content_for :scripts_body_top do
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 30622d8a910..f0a3e416db7 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -1,14 +1,15 @@
- if event = last_push_event
- if show_last_push_widget?(event)
- .hidden-xs.center
- .slead
- %span You pushed to
- = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
- %strong= event.ref_name
- branch
- #{time_ago_with_tooltip(event.created_at)}
- %div
- = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do
- Create Merge Request
- %hr
+ .gray-content-block.top-block.clear-block.hidden-xs
+ .event-last-push
+ .event-last-push-text
+ %span You pushed to
+ = link_to namespace_project_commits_path(event.project.namespace, event.project, event.ref_name) do
+ %strong= event.ref_name
+ branch
+ #{time_ago_with_tooltip(event.created_at)}
+
+ .pull-right
+ = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn btn-info btn-sm" do
+ Create Merge Request
diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml
index 13f8271b979..5b61846fe6d 100644
--- a/app/views/projects/blob/_actions.html.haml
+++ b/app/views/projects/blob/_actions.html.haml
@@ -17,6 +17,6 @@
tree_join(@commit.sha, @path)), class: 'btn btn-sm'
- if allowed_tree_edit?
- = button_tag class: 'remove-blob btn btn-sm btn-remove',
- 'data-toggle' => 'modal', 'data-target' => '#modal-remove-blob' do
- Remove
+ .btn-group{:role => "group"}
+ %button.btn.btn-default{class: 'btn-primary', href: '#modal-replace-blob', 'data-target' => '#modal-replace-blob', 'data-toggle' => 'modal'} Replace
+ %button.btn.btn-default{class: 'btn-remove', href: '#modal-remove-blob', 'data-target' => '#modal-remove-blob', 'data-toggle' => 'modal'} Remove
diff --git a/app/views/projects/blob/_replace.html.haml b/app/views/projects/blob/_replace.html.haml
new file mode 100644
index 00000000000..84abf0303d0
--- /dev/null
+++ b/app/views/projects/blob/_replace.html.haml
@@ -0,0 +1,28 @@
+#modal-replace-blob.modal
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %a.close{href: "#", "data-dismiss" => "modal"} ×
+ %h3.page-title Replace #{@blob.name}
+ %p.light
+ From branch
+ %strong= @ref
+ .modal-body
+ = form_tag namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'blob-file-upload-form-js form-horizontal' do
+ .dropzone
+ .dropzone-previews{class: "blob-upload-dropzone-previews"}
+ %p.dz-message{class: "hint"}<
+ Attach files by dragging & dropping or&nbsp;
+ %a{href: '#', class: "markdown-selector"}>click to upload
+ %br
+ .dropzone-alerts{class: "alert alert-danger data", "data-dismiss" => "alert", style: "display:none"}
+ = render 'shared/commit_message_container', params: params,
+ placeholder: 'Replace this file because...'
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ = button_tag 'Replace file', class: 'btn btn-small btn-primary btn-replace-file', id: 'submit-all'
+ = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+
+:coffeescript
+ disableButtonIfEmptyField $('.blob-file-upload-form-js').find('#commit_message'), '.btn-replace-file'
+ new BlobFileDropzone($('.blob-file-upload-form-js'), 'put')
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
new file mode 100644
index 00000000000..5a6a3358a17
--- /dev/null
+++ b/app/views/projects/blob/_upload.html.haml
@@ -0,0 +1,28 @@
+#modal-upload-blob.modal
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %a.close{href: "#", "data-dismiss" => "modal"} ×
+ %h3.page-title Upload
+ %p.light
+ From branch
+ %strong= @ref
+ .modal-body
+ = form_tag namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'blob-file-upload-form-js form-horizontal' do
+ .dropzone
+ .dropzone-previews{class: "blob-upload-dropzone-previews"}
+ %p.dz-message{class: "hint"}<
+ Attach files by dragging & dropping or&nbsp;
+ %a{href: '#', class: "markdown-selector"}>click to upload
+ %br
+ .dropzone-alerts{class: "alert alert-danger data", "data-dismiss" => "alert", style: "display:none"}
+ = render 'shared/commit_message_container', params: params,
+ placeholder: 'Upload this file because...'
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ = button_tag 'Upload file', class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all'
+ = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
+
+:coffeescript
+ disableButtonIfEmptyField $('.blob-file-upload-form-js').find('#commit_message'), '.btn-upload-file'
+ new BlobFileDropzone($('.blob-file-upload-form-js'), 'post')
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index a12cd660fc1..648f15418e0 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -1,6 +1,6 @@
- page_title "Edit", @blob.path, @ref
.file-editor
- %ul.nav.nav-tabs.js-edit-mode
+ %ul.center-top-menu.no-bottom.js-edit-mode
%li.active
= link_to '#editor' do
%i.fa.fa-edit
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 7c2a4fece94..6fb46ea2040 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -1,5 +1,11 @@
-- page_title "New File", @ref
-%h3.page-title New file
+%h3.page-title<
+ Create new file or&nbsp;
+ %a.upload-link{href: '#modal-upload-blob', 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'}>upload existing one
+
+.file-title
+ = render 'projects/blob/upload'
+ %br
+
.file-editor
= form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file js-requires-input') do
= render 'projects/blob/editor', ref: @ref
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index bd2fc43633c..19e876ec34c 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -10,3 +10,4 @@
- if allowed_tree_edit?
= render 'projects/blob/remove'
+ = render 'projects/blob/replace'
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index 50c0fd6803d..a849bf84698 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -1,10 +1,10 @@
%ul.center-top-menu
= nav_link(controller: [:commit, :commits]) do
- = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
+ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
Commits
%span.badge= number_with_delimiter(@repository.commit_count)
= nav_link(controller: :compare) do
- = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: @ref || @repository.root_ref) do
+ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: current_ref) do
Compare
= nav_link(html_options: {class: branches_tab_class}) do
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index d44fe486212..284adb40e97 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -1,14 +1,15 @@
- page_title "Labels"
-- if can? current_user, :admin_label, @project
- = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do
- New label
-%h3.page-title
- Labels
-%hr
+
+.gray-content-block.top-block
+ - if can? current_user, :admin_label, @project
+ = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do
+ New label
+ .oneline
+ Labels can be applied to issues and merge requests.
.labels
- if @labels.present?
- %ul.bordered-list.manage-labels-list
+ %ul.content-list.manage-labels-list
= render @labels
= paginate @labels, theme: 'gitlab'
- else
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 162583e4b1d..a40d1513671 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -1,30 +1,28 @@
- page_title "Members"
-%h3.page-title
- Users with access to this project
-%p.light
+.gray-content-block.top-block
+ .clearfix.js-toggle-container
+ = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
+ .form-group
+ = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' }
+ = button_tag 'Search', class: 'btn'
+
+ - if can?(current_user, :admin_project_member, @project)
+ %span.pull-right
+ = button_tag class: 'btn btn-new btn-grouped js-toggle-button', type: 'button' do
+ Add members
+ %i.fa.fa-chevron-down
+ = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do
+ Import members
+
+ .js-toggle-content.hide.new-group-member-holder
+ = render "new_project_member"
+
+%p.prepend-top-default.light
+ Users with access to this project are listed below.
Read more about project permissions
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
-%hr
-
-.clearfix.js-toggle-container
- = form_tag namespace_project_project_members_path(@project.namespace, @project), method: :get, class: 'form-inline member-search-form' do
- .form-group
- = search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input' }
- = button_tag 'Search', class: 'btn'
-
- - if can?(current_user, :admin_project_member, @project)
- %span.pull-right
- = button_tag class: 'btn btn-new btn-grouped js-toggle-button', type: 'button' do
- Add members
- %i.fa.fa-chevron-down
- = link_to import_namespace_project_project_members_path(@project.namespace, @project), class: "btn btn-grouped", title: "Import members from another project" do
- Import members
-
- .js-toggle-content.hide.new-group-member-holder
- = render "new_project_member"
-
= render "team", members: @project_members
- if @group
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index d5c4ee71978..aa5914e3ed9 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -14,7 +14,7 @@
.project-stats.gray-content-block
%ul.nav.nav-pills
%li
- = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref) do
+ = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
= pluralize(number_with_delimiter(@project.commit_count), 'commit')
%li
= link_to namespace_project_branches_path(@project.namespace, @project) do
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index aa4e8722fb1..37d5dba0330 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -16,8 +16,8 @@
- if @user == current_user
.pull-right.hidden-xs
= link_to profile_path, class: 'btn btn-sm' do
- %i.fa.fa-pencil-square-o
- Edit Profile settings
+ = icon('user')
+ Profile settings
- elsif current_user
.pull-right
%span.dropdown
diff --git a/config/routes.rb b/config/routes.rb
index fad6b3c569a..54e109f34fa 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -358,6 +358,16 @@ Gitlab::Application.routes.draw do
to: 'blob#destroy',
constraints: { id: /.+/, format: false }
)
+ put(
+ '/blob/*id',
+ to: 'blob#update',
+ constraints: { id: /.+/, format: false }
+ )
+ post(
+ '/blob/*id',
+ to: 'blob#create',
+ constraints: { id: /.+/, format: false }
+ )
end
scope do
diff --git a/features/project/source/browse_files.feature b/features/project/source/browse_files.feature
index d3a77466a35..b5b6abe6aff 100644
--- a/features/project/source/browse_files.feature
+++ b/features/project/source/browse_files.feature
@@ -33,6 +33,29 @@ Feature: Project Source Browse Files
And I click on "Commit Changes"
Then I am redirected to the new file
And I should see its new content
+
+ @javascript
+ Scenario: I can upload file and commit
+ Given I click on "new file" link in repo
+ Then I can see new file page
+ And I can see "upload existing one"
+ And I click on "upload existing one"
+ And I upload a new text file
+ And I fill the upload file commit message
+ And I click on "Upload file"
+ Then I can see the new text file
+ And I can see the new commit message
+
+ @javascript
+ Scenario: I can replace file and commit
+ Given I click on ".gitignore" file in repo
+ And I see the ".gitignore"
+ And I click on "Replace"
+ And I replace it with a text file
+ And I fill the replace file commit message
+ And I click on "Replace file"
+ Then I can see the new text file
+ And I can see the replacement commit message
@javascript
Scenario: I can create and commit file and specify new branch
diff --git a/features/steps/project/source/browse_files.rb b/features/steps/project/source/browse_files.rb
index 5cb085db207..7a0ee4df45e 100644
--- a/features/steps/project/source/browse_files.rb
+++ b/features/steps/project/source/browse_files.rb
@@ -1,3 +1,4 @@
+# coding: utf-8
class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
@@ -78,7 +79,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I fill the commit message' do
- fill_in :commit_message, with: 'Not yet a commit message.'
+ fill_in :commit_message, with: 'Not yet a commit message.', visible: true
end
step 'I click link "Diff"' do
@@ -97,6 +98,14 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
click_button 'Remove file'
end
+ step 'I click on "Replace"' do
+ click_button "Replace"
+ end
+
+ step 'I click on "Replace file"' do
+ click_button 'Replace file'
+ end
+
step 'I see diff' do
expect(page).to have_css '.line_holder.new'
end
@@ -106,10 +115,55 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I can see new file page' do
- expect(page).to have_content "New file"
+ expect(page).to have_content "new file"
expect(page).to have_content "Commit message"
end
+ step 'I can see "upload existing one"' do
+ expect(page).to have_content "upload existing one"
+ end
+
+ step 'I click on "upload existing one"' do
+ click_link 'upload existing one'
+ end
+
+ step 'I click on "Upload file"' do
+ click_button 'Upload file'
+ end
+
+ step 'I can see the new commit message' do
+ expect(page).to have_content "New upload commit message"
+ end
+
+ step 'I upload a new text file' do
+ drop_in_dropzone test_text_file
+ end
+
+ step 'I fill the upload file commit message' do
+ page.within('#modal-upload-blob') do
+ fill_in :commit_message, with: 'New upload commit message'
+ end
+ end
+
+ step 'I replace it with a text file' do
+ drop_in_dropzone test_text_file
+ end
+
+ step 'I fill the replace file commit message' do
+ page.within('#modal-replace-blob') do
+ fill_in :commit_message, with: 'Replacement file commit message'
+ end
+ end
+
+ step 'I can see the replacement commit message' do
+ expect(page).to have_content "Replacement file commit message"
+ end
+
+ step 'I can see the new text file' do
+ expect(page).to have_content "Lorem ipsum dolor sit amet"
+ expect(page).to have_content "Sed ut perspiciatis unde omnis"
+ end
+
step 'I click on files directory' do
click_link 'files'
end
@@ -232,4 +286,29 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
def new_file_name
'not_a_file.md'
end
+
+ def drop_in_dropzone(file_path)
+ # Generate a fake input selector
+ page.execute_script <<-JS
+ var fakeFileInput = window.$('<input/>').attr(
+ {id: 'fakeFileInput', type: 'file'}
+ ).appendTo('body');
+ JS
+ # Attach the file to the fake input selector with Capybara
+ attach_file("fakeFileInput", file_path)
+ # Add the file to a fileList array and trigger the fake drop event
+ page.execute_script <<-JS
+ var fileList = [$('#fakeFileInput')[0].files[0]];
+ var e = jQuery.Event('drop', { dataTransfer : { files : fileList } });
+ $('.dropzone')[0].dropzone.listeners[0].events.drop(e);
+ JS
+ end
+
+ def test_text_file
+ File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt')
+ end
+
+ def test_image_file
+ File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif')
+ end
end