diff options
Diffstat (limited to 'app')
64 files changed, 706 insertions, 377 deletions
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index 86ccd8c21ed..9add1304dc7 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -34,6 +34,7 @@ #= require dropzone #= require semantic-ui/sidebar #= require mousetrap +#= require mousetrap/pause #= require shortcuts #= require shortcuts_navigation #= require shortcuts_dashboard_navigation diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index ae4cf577179..086c09f196e 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -24,18 +24,22 @@ class Dispatcher when 'projects:issues:show' new Issue() shortcut_handler = new ShortcutsIssueable() + new ZenMode() when 'projects:milestones:show' new Milestone() - when 'projects:issues:new' + when 'projects:issues:new','projects:issues:edit' GitLab.GfmAutoComplete.setup() shortcut_handler = new ShortcutsNavigation() - when 'projects:merge_requests:new' + new ZenMode() + when 'projects:merge_requests:new', 'projects:merge_requests:edit' GitLab.GfmAutoComplete.setup() new Diff() shortcut_handler = new ShortcutsNavigation() + new ZenMode() when 'projects:merge_requests:show' new Diff() shortcut_handler = new ShortcutsIssueable() + new ZenMode() when "projects:merge_requests:diffs" new Diff() when 'projects:merge_requests:index' diff --git a/app/assets/javascripts/markdown_area.js.coffee b/app/assets/javascripts/markdown_area.js.coffee index bee2785562d..a971e5dbf1d 100644 --- a/app/assets/javascripts/markdown_area.js.coffee +++ b/app/assets/javascripts/markdown_area.js.coffee @@ -27,7 +27,7 @@ $(document).ready -> dropzone = $(".div-dropzone").dropzone( url: project_image_path_upload dictDefaultMessage: "" - clickable: true + clickable: false paramName: "markdown_img" maxFilesize: 10 uploadMultiple: false diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index 51c617bd584..597d6d26b69 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -26,6 +26,7 @@ class Notes # Reopen and close actions for Issue/MR combined with note form submit $(document).on "click", ".js-note-target-reopen", @targetReopen $(document).on "click", ".js-note-target-close", @targetClose + $(document).on "click", ".js-comment-button", @updateCloseButton $(document).on "keyup", ".js-note-text", @updateTargetButtons # remove a note (in general) @@ -496,6 +497,11 @@ class Notes if noteText.trim().length > 0 form.submit() + updateCloseButton: (e) => + textarea = $(e.target) + form = textarea.parents('form') + form.find('.js-note-target-close').text('Close') + updateTargetButtons: (e) => textarea = $(e.target) form = textarea.parents('form') diff --git a/app/assets/javascripts/zen_mode.js.coffee b/app/assets/javascripts/zen_mode.js.coffee new file mode 100644 index 00000000000..aea707d8550 --- /dev/null +++ b/app/assets/javascripts/zen_mode.js.coffee @@ -0,0 +1,51 @@ +class @ZenMode + @fullscreen_prefix = 'fullscreen_' + @ESC = 27 + + constructor: -> + @active_zen_area = null + @active_checkbox = null + + $('body').on 'change', '.zennable input[type=checkbox]', (e) => + checkbox = e.currentTarget; + if checkbox.checked + Mousetrap.pause() + @udpateActiveZenArea(checkbox) + else + @exitZenMode() + + $(document).on 'keydown', (e) => + console.log("esc") + if e.keyCode is ZenMode.ESC + @exitZenMode() + + $(window).on 'hashchange', @updateZenModeFromLocationHash + + udpateActiveZenArea: (checkbox) => + @active_checkbox = $(checkbox) + @active_checkbox.prop('checked', true) + @active_zen_area = @active_checkbox.parent().find('textarea') + @active_zen_area.focus() + window.location.hash = ZenMode.fullscreen_prefix + @active_checkbox.prop('id') + + exitZenMode: => + if @active_zen_area isnt null + Mousetrap.unpause() + @active_checkbox.prop('checked', false) + @active_zen_area = null + @active_checkbox = null + window.location.hash = '' + + checkboxFromLocationHash: (e) -> + id = $.trim(window.location.hash.replace('#' + ZenMode.fullscreen_prefix, '')) + if id + return $('.zennable input[type=checkbox]#' + id)[0] + else + return null + + updateZenModeFromLocationHash: (e) => + checkbox = @checkboxFromLocationHash() + if checkbox + @udpateActiveZenArea(checkbox) + else + @exitZenMode() diff --git a/app/assets/stylesheets/generic/forms.scss b/app/assets/stylesheets/generic/forms.scss index 2a31cae5dfb..3b90c4f27f0 100644 --- a/app/assets/stylesheets/generic/forms.scss +++ b/app/assets/stylesheets/generic/forms.scss @@ -83,3 +83,140 @@ label { .form-control { @include box-shadow(none); } + +.issuable-description { + margin-top: 35px; +} + +.zennable { + position: relative; + + input { + display: none; + } + + .collapse { + display: none; + opacity: 0.5; + + &:before { + content: '\f066'; + font-family: FontAwesome; + color: #000; + font-size: 28px; + position: relative; + padding: 30px 40px 0 0; + } + + &:hover { + opacity: 0.8; + } + } + + .expand { + opacity: 0.5; + + &:before { + content: '\f065'; + font-family: FontAwesome; + color: #000; + font-size: 14px; + line-height: 14px; + padding-right: 20px; + position: relative; + vertical-align: middle; + } + + &:hover { + opacity: 0.8; + } + } + + input:checked ~ .zen-backdrop .expand { + display: none; + } + + input:checked ~ .zen-backdrop .collapse { + display: block; + position: absolute; + top: 0; + } + + label { + position: absolute; + top: -26px; + right: 0; + font-variant: small-caps; + text-transform: uppercase; + font-size: 10px; + padding: 4px; + font-weight: 500; + letter-spacing: 1px; + + &:before { + display: inline-block; + width: 10px; + height: 14px; + } + } + + input:checked ~ .zen-backdrop { + background-color: white; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1031; + + textarea { + border: none; + box-shadow: none; + border-radius: 0; + color: #000; + font-size: 20px; + line-height: 26px; + padding: 30px; + display: block; + outline: none; + resize: none; + height: 100vh; + max-width: 900px; + margin: 0 auto; + } + } + + .zen-backdrop textarea::-webkit-input-placeholder { + color: white; + } + + .zen-backdrop textarea:-moz-placeholder { + color: white; + } + + .zen-backdrop textarea::-moz-placeholder { + color: white; + } + + .zen-backdrop textarea:-ms-input-placeholder { + color: white; + } + + input:checked ~ .zen-backdrop textarea::-webkit-input-placeholder { + color: #999; + } + + input:checked ~ .zen-backdrop textarea:-moz-placeholder { + color: #999; + opacity: 1; + } + + input:checked ~ .zen-backdrop textarea::-moz-placeholder { + color: #999; + opacity: 1; + } + + input:checked ~ .zen-backdrop textarea:-ms-input-placeholder { + color: #999; + } +} diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 47802559a2c..385a627b4be 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -89,6 +89,8 @@ a:focus { .wiki { @include md-typography; + word-wrap: break-word; + /* Link to current header. */ h1, h2, h3, h4, h5, h6 { position: relative; diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb index ca83b21f429..72a41f771c0 100644 --- a/app/controllers/projects/edit_tree_controller.rb +++ b/app/controllers/projects/edit_tree_controller.rb @@ -31,7 +31,7 @@ class Projects::EditTreeController < Projects::BaseTreeController diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true) - @diff = Gitlab::DiffParser.new(diffy.diff.scan(/.*\n/)) + @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/)) render layout: false end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f23afaf28fa..b3380a6ff23 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -103,7 +103,15 @@ class ProjectsController < ApplicationController ::Projects::DestroyService.new(@project, current_user, {}).execute respond_to do |format| - format.html { redirect_to root_path } + format.html do + flash[:alert] = "Project deleted." + + if request.referer.include?("/admin") + redirect_to admin_projects_path + else + redirect_to projects_dashboard_path + end + end end end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index a58b24de643..55926a1ed22 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -5,15 +5,23 @@ class SearchController < ApplicationController @project = Project.find_by(id: params[:project_id]) if params[:project_id].present? @group = Group.find_by(id: params[:group_id]) if params[:group_id].present? @scope = params[:scope] + @show_snippets = params[:snippets].eql? 'true' @search_results = if @project return access_denied! unless can?(current_user, :download_code, @project) - unless %w(blobs notes issues merge_requests).include?(@scope) + unless %w(blobs notes issues merge_requests wiki_blobs). + include?(@scope) @scope = 'blobs' end Search::ProjectService.new(@project, current_user, params).execute + elsif @show_snippets + unless %w(snippet_blobs snippet_titles).include?(@scope) + @scope = 'snippet_blobs' + end + + Search::SnippetService.new(current_user, params).execute else unless %w(projects issues merge_requests).include?(@scope) @scope = 'projects' diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e6d50bea4d1..c2c9301cc17 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -178,6 +178,8 @@ module ApplicationHelper def search_placeholder if @project && @project.persisted? "Search in this project" + elsif @snippet || @snippets || @show_snippets + 'Search snippets' elsif @group && @group.persisted? "Search in this group" else diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f61aa259154..cab2984a4c4 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -16,38 +16,6 @@ module CommitsHelper commit_person_link(commit, options.merge(source: :committer)) end - def each_diff_line(diff, index) - Gitlab::DiffParser.new(diff.diff.lines.to_a, diff.new_path) - .each do |full_line, type, line_code, line_new, line_old| - yield(full_line, type, line_code, line_new, line_old) - end - end - - def each_diff_line_near(diff, index, expected_line_code) - max_number_of_lines = 16 - - prev_match_line = nil - prev_lines = [] - - each_diff_line(diff, index) do |full_line, type, line_code, line_new, line_old| - line = [full_line, type, line_code, line_new, line_old] - if line_code != expected_line_code - if type == "match" - prev_lines.clear - prev_match_line = line - else - prev_lines.push(line) - prev_lines.shift if prev_lines.length >= max_number_of_lines - end - else - yield(prev_match_line) if !prev_match_line.nil? - prev_lines.each { |ln| yield(ln) } - yield(line) - break - end - end - end - def image_diff_class(diff) if diff.deleted_file "deleted" @@ -63,14 +31,6 @@ module CommitsHelper escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil? end - def diff_line_content(line) - if line.blank? - " " - else - line - end - end - # Breadcrumb links for a Project and, if applicable, a tree path def commits_breadcrumbs return unless @project && @ref @@ -105,82 +65,6 @@ module CommitsHelper branches.sort.map { |branch| link_to(branch, project_tree_path(project, branch)) }.join(", ").html_safe end - def parallel_diff_lines(project, commit, diff, file) - old_file = project.repository.blob_at(commit.parent_id, diff.old_path) if commit.parent_id - deleted_lines = {} - added_lines = {} - each_diff_line(diff, 0) do |line, type, line_code, line_new, line_old| - if type == "old" - deleted_lines[line_old] = { line_code: line_code, type: type, line: line } - elsif type == "new" - added_lines[line_new] = { line_code: line_code, type: type, line: line } - end - end - max_length = old_file ? [old_file.loc, file.loc].max : file.loc - - offset1 = 0 - offset2 = 0 - old_lines = [] - new_lines = [] - - max_length.times do |line_index| - line_index1 = line_index - offset1 - line_index2 = line_index - offset2 - deleted_line = deleted_lines[line_index1 + 1] - added_line = added_lines[line_index2 + 1] - old_line = old_file.lines[line_index1] if old_file - new_line = file.lines[line_index2] - - if deleted_line && added_line - elsif deleted_line - new_line = nil - offset2 += 1 - elsif added_line - old_line = nil - offset1 += 1 - end - - old_lines[line_index] = DiffLine.new - new_lines[line_index] = DiffLine.new - - # old - if line_index == 0 && diff.new_file - old_lines[line_index].type = :file_created - old_lines[line_index].content = 'File was created' - elsif deleted_line - old_lines[line_index].type = :deleted - old_lines[line_index].content = old_line - old_lines[line_index].num = line_index1 + 1 - old_lines[line_index].code = deleted_line[:line_code] - elsif old_line - old_lines[line_index].type = :no_change - old_lines[line_index].content = old_line - old_lines[line_index].num = line_index1 + 1 - else - old_lines[line_index].type = :added - end - - # new - if line_index == 0 && diff.deleted_file - new_lines[line_index].type = :file_deleted - new_lines[line_index].content = "File was deleted" - elsif added_line - new_lines[line_index].type = :added - new_lines[line_index].num = line_index2 + 1 - new_lines[line_index].content = new_line - new_lines[line_index].code = added_line[:line_code] - elsif new_line - new_lines[line_index].type = :no_change - new_lines[line_index].num = line_index2 + 1 - new_lines[line_index].content = new_line - else - new_lines[line_index].type = :deleted - end - end - - return old_lines, new_lines - end - def link_to_browse_code(project, commit) if current_controller?(:projects, :commits) if @repo.blob_at(commit.id, @path) @@ -229,14 +113,6 @@ module CommitsHelper end end - def diff_file_mode_changed?(diff) - diff.a_mode && diff.b_mode && diff.a_mode != diff.b_mode - end - - def unfold_bottom_class(bottom) - (bottom) ? 'js-unfold-bottom' : '' - end - def view_file_btn(commit_sha, diff, project) link_to project_blob_path(project, tree_join(commit_sha, diff.new_path)), class: 'btn btn-small view-file js-view-file' do diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index ee4d4fbdff5..afe7447d4e2 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -1,14 +1,20 @@ module DiffHelper - def safe_diff_files(diffs) + def allowed_diff_size if diff_hard_limit_enabled? - diffs.first(Commit::DIFF_HARD_LIMIT_FILES) + Commit::DIFF_HARD_LIMIT_FILES else - diffs.first(Commit::DIFF_SAFE_FILES) + Commit::DIFF_SAFE_FILES + end + end + + def safe_diff_files(diffs) + diffs.first(allowed_diff_size).map do |diff| + Gitlab::Diff::File.new(diff) end end - def show_diff_size_warninig?(diffs) - safe_diff_files(diffs).size < diffs.size + def show_diff_size_warning?(diffs) + diffs.size > allowed_diff_size end def diff_hard_limit_enabled? @@ -19,4 +25,76 @@ module DiffHelper false end end + + def generate_line_code(file_path, line) + Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) + end + + def parallel_diff(diff_file, index) + lines = [] + skip_next = false + + # Building array of lines + # + # [left_type, left_line_number, left_line_content, line_code, right_line_type, right_line_number, right_line_content] + # + diff_file.diff_lines.each do |line| + + full_line = line.text + type = line.type + line_code = generate_line_code(diff_file.file_path, line) + line_new = line.new_pos + line_old = line.old_pos + + next_line = diff_file.next_line(line.index) + + if next_line + next_type = next_line.type + next_line = next_line.text + end + + line = [type, line_old, full_line, line_code, next_type, line_new] + if type == 'match' || type.nil? + # line in the right panel is the same as in the left one + line = [type, line_old, full_line, line_code, type, line_new, full_line] + lines.push(line) + elsif type == 'old' + if next_type == 'new' + # Left side has text removed, right side has text added + line.push(next_line) + lines.push(line) + skip_next = true + elsif next_type == 'old' || next_type.nil? + # Left side has text removed, right side doesn't have any change + line.pop # remove the newline + line.push(nil) # no line number on the right panel + line.push(" ") # empty line on the right panel + lines.push(line) + end + elsif type == 'new' + if skip_next + # Change has been already included in previous line so no need to do it again + skip_next = false + next + else + # Change is only on the right side, left side has no change + line = [nil, nil, " ", line_code, type, line_new, full_line] + lines.push(line) + end + end + end + lines + end + + def unfold_bottom_class(bottom) + (bottom) ? 'js-unfold-bottom' : '' + end + + def diff_line_content(line) + if line.blank? + " " + else + line + end + end end diff --git a/app/models/note.rb b/app/models/note.rb index 7cbab1130ea..fa5fdea4eb0 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -209,9 +209,10 @@ class Note < ActiveRecord::Base noteable.diffs.each do |mr_diff| next unless mr_diff.new_path == self.diff.new_path - Gitlab::DiffParser.new(mr_diff.diff.lines.to_a, mr_diff.new_path). - each do |full_line, type, line_code, line_new, line_old| - if full_line == diff_line + lines = Gitlab::Diff::Parser.new.parse(mr_diff.diff.lines.to_a) + + lines.each do |line| + if line.text == diff_line return true end end @@ -232,6 +233,14 @@ class Note < ActiveRecord::Base diff.new_path if diff end + def file_path + if diff.new_path.present? + diff.new_path + elsif diff.old_path.present? + diff.old_path + end + end + def diff_old_line line_code.split('_')[1].to_i end @@ -240,19 +249,49 @@ class Note < ActiveRecord::Base line_code.split('_')[2].to_i end + def generate_line_code(line) + Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos) + end + def diff_line return @diff_line if @diff_line if diff - Gitlab::DiffParser.new(diff.diff.lines.to_a, diff.new_path) - .each do |full_line, type, line_code, line_new, line_old| - @diff_line = full_line if line_code == self.line_code + diff_lines.each do |line| + if generate_line_code(line) == self.line_code + @diff_line = line.text end + end end @diff_line end + def truncated_diff_lines + max_number_of_lines = 16 + prev_match_line = nil + prev_lines = [] + + diff_lines.each do |line| + if generate_line_code(line) != self.line_code + if line.type == "match" + prev_lines.clear + prev_match_line = line + else + prev_lines.push(line) + prev_lines.shift if prev_lines.length >= max_number_of_lines + end + else + prev_lines << line + return prev_lines + end + end + end + + def diff_lines + @diff_lines ||= Gitlab::Diff::Parser.new.parse(diff.diff.lines.to_a) + end + def discussion_id @discussion_id ||= Note.build_discussion_id(noteable_type, noteable_id || commit_id, line_code) end diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb index 9a8cbb32ac1..3421a0330aa 100644 --- a/app/models/project_services/assembla_service.rb +++ b/app/models/project_services/assembla_service.rb @@ -5,21 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class AssemblaService < Service include HTTParty + prop_accessor :token, :subdomain validates :token, presence: true, if: :activated? def title diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb index 83e1bac1ef2..2d8950db491 100644 --- a/app/models/project_services/campfire_service.rb +++ b/app/models/project_services/campfire_service.rb @@ -5,19 +5,15 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class CampfireService < Service + prop_accessor :token, :subdomain, :room validates :token, presence: true, if: :activated? def title diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb index 1a107f92c93..829f495abc6 100644 --- a/app/models/project_services/ci_service.rb +++ b/app/models/project_services/ci_service.rb @@ -5,16 +5,11 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # # Base class for CI services diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index be5bab4ec32..5c4537cfca5 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -5,19 +5,15 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class EmailsOnPushService < Service + prop_accessor :recipients validates :recipients, presence: true, if: :activated? def title diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 6cdd04a8648..4d11b00c192 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -5,21 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # require "flowdock-git-hook" class FlowdockService < Service + prop_accessor :token validates :token, presence: true, if: :activated? def title diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb index b363d7f57d2..7b6c87e4cec 100644 --- a/app/models/project_services/gemnasium_service.rb +++ b/app/models/project_services/gemnasium_service.rb @@ -5,21 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # require "gemnasium/gitlab_service" class GemnasiumService < Service + prop_accessor :token, :api_key validates :token, :api_key, presence: true, if: :activated? def title diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb index 58ddce45288..0f327e75289 100644 --- a/app/models/project_services/gitlab_ci_service.rb +++ b/app/models/project_services/gitlab_ci_service.rb @@ -5,19 +5,15 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# property :text # class GitlabCiService < CiService + prop_accessor :project_url, :token validates :project_url, presence: true, if: :activated? validates :token, presence: true, if: :activated? diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 256debffc51..3a1ba168e6a 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -5,21 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class HipchatService < Service MAX_COMMITS = 3 + prop_accessor :token, :room validates :token, presence: true, if: :activated? def title diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb index aa2bcc5def7..3aa928b92a0 100644 --- a/app/models/project_services/pivotaltracker_service.rb +++ b/app/models/project_services/pivotaltracker_service.rb @@ -5,21 +5,17 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class PivotaltrackerService < Service include HTTParty + prop_accessor :token validates :token, presence: true, if: :activated? def title diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index 7e54188abf7..4bda93f6006 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -5,19 +5,15 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) +# properties :text # class SlackService < Service + prop_accessor :room, :subdomain, :token validates :room, presence: true, if: :activated? validates :subdomain, presence: true, if: :activated? validates :token, presence: true, if: :activated? diff --git a/app/models/service.rb b/app/models/service.rb index 0dc6d514b46..1f3a6520473 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -5,23 +5,21 @@ # id :integer not null, primary key # type :string(255) # title :string(255) -# token :string(255) # project_id :integer not null # created_at :datetime # updated_at :datetime # active :boolean default(FALSE), not null -# project_url :string(255) -# subdomain :string(255) -# room :string(255) -# recipients :text -# api_key :string(255) -# +# properties :text # To add new service you should build a class inherited from Service # and implement a set of methods class Service < ActiveRecord::Base + serialize :properties, JSON + default_value_for :active, false + after_initialize :initialize_properties + belongs_to :project has_one :service_hook @@ -35,6 +33,10 @@ class Service < ActiveRecord::Base :common end + def initialize_properties + self.properties = {} if properties.nil? + end + def title # implement inside child end @@ -63,4 +65,20 @@ class Service < ActiveRecord::Base def can_test? !project.empty_repo? end + + # Provide convenient accessor methods + # for each serialized property. + def self.prop_accessor(*args) + args.each do |arg| + class_eval %{ + def #{arg} + properties['#{arg}'] + end + + def #{arg}=(value) + self.properties['#{arg}'] = value + end + } + end + end end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 2c38e7939bd..80c1af8f337 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -65,4 +65,18 @@ class Snippet < ActiveRecord::Base def expired? expires_at && expires_at < Time.current end + + class << self + def search(query) + where('(title LIKE :query OR file_name LIKE :query)', query: "%#{query}%") + end + + def search_code(query) + where('(content LIKE :query)', query: "%#{query}%") + end + + def accessible_to(user) + where('private = ? OR author_id = ?', false, user) + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index f1ff76edd15..15e56a62a68 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -474,10 +474,6 @@ class User < ActiveRecord::Base email =~ /\Atemp-email-for-oauth/ end - def generate_tmp_oauth_email - self.email = "temp-email-for-oauth-#{username}@gitlab.localhost" - end - def public_profile? authorized_projects.public_only.any? end diff --git a/app/services/search/snippet_service.rb b/app/services/search/snippet_service.rb new file mode 100644 index 00000000000..8ca0877321d --- /dev/null +++ b/app/services/search/snippet_service.rb @@ -0,0 +1,14 @@ +module Search + class SnippetService + attr_accessor :current_user, :params + + def initialize(user, params) + @current_user, @params = user, params.dup + end + + def execute + snippet_ids = Snippet.accessible_to(current_user).pluck(:id) + Gitlab::SnippetSearchResults.new(snippet_ids, params[:search]) + end + end +end diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index f485aee1e1a..5ab82122ad7 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -5,6 +5,8 @@ - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id = hidden_field_tag :search_code, true + - if @snippet || @snippets + = hidden_field_tag :snippets, true = hidden_field_tag :repository_ref, @ref = submit_tag 'Go' if ENV['RAILS_ENV'] == 'test' .search-autocomplete-opts.hide{:'data-autocomplete-path' => search_autocomplete_path, :'data-autocomplete-project-id' => @project.try(:id), :'data-autocomplete-project-ref' => @ref } diff --git a/app/views/projects/_issuable_form.html.haml b/app/views/projects/_issuable_form.html.haml index f7c4673b52d..402cdb44182 100644 --- a/app/views/projects/_issuable_form.html.haml +++ b/app/views/projects/_issuable_form.html.haml @@ -4,11 +4,15 @@ .col-sm-10 = f.text_field :title, maxlength: 255, autofocus: true, class: 'form-control pad js-gfm-input', required: true -.form-group +.form-group.issuable-description = f.label :description, 'Description', class: 'control-label' .col-sm-10 - = f.text_area :description, rows: 14, - class: 'form-control js-gfm-input markdown-area' + .zennable + %input#zen-toggle-comment{ tabindex: '-1', type: 'checkbox' } + .zen-backdrop + = f.text_area :description, rows: 14, class: 'form-control js-gfm-input markdown-area', placeholder: 'Leave a comment' + %label{ for: 'zen-toggle-comment', class: 'expand' } Edit in fullscreen + %label{ for: 'zen-toggle-comment', class: 'collapse' } .col-sm-12.hint .pull-left Parsed with diff --git a/app/views/projects/blob/diff.html.haml b/app/views/projects/blob/diff.html.haml index cfb91d6568a..5c79d0ef11f 100644 --- a/app/views/projects/blob/diff.html.haml +++ b/app/views/projects/blob/diff.html.haml @@ -1,7 +1,7 @@ - if @lines.present? - if @form.unfold? && @form.since != 1 && !@form.bottom? %tr.line_holder{ id: @form.since } - = render "projects/commits/diffs/match_line", {line: @match_line, + = render "projects/diffs/match_line", {line: @match_line, line_old: @form.since, line_new: @form.since, bottom: false} - @lines.each_with_index do |line, index| @@ -15,5 +15,5 @@ - if @form.unfold? && @form.bottom? && @form.to < @blob.loc %tr.line_holder{ id: @form.to } - = render "projects/commits/diffs/match_line", {line: @match_line, + = render "projects/diffs/match_line", {line: @match_line, line_old: @form.to, line_new: @form.to, bottom: true} diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 0a15aef6cb7..fc721067ed4 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,3 +1,3 @@ = render "commit_box" -= render "projects/commits/diffs", diffs: @diffs, project: @project += render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form" diff --git a/app/views/projects/commits/_diff_file.html.haml b/app/views/projects/commits/_diff_file.html.haml deleted file mode 100644 index 31208a227ce..00000000000 --- a/app/views/projects/commits/_diff_file.html.haml +++ /dev/null @@ -1,48 +0,0 @@ -- file = project.repository.blob_for_diff(@commit, diff) -- return unless file -- blob_diff_path = diff_project_blob_path(project, - tree_join(@commit.id, diff.new_path)) -.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }} - .diff-header{id: "file-path-#{hexdigest(diff.new_path || diff.old_path)}"} - - if diff.deleted_file - %span= diff.old_path - - .diff-btn-group - - if @commit.parent_ids.present? - = view_file_btn(@commit.parent_id, diff, project) - - else - %span= diff.new_path - - if diff_file_mode_changed?(diff) - %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" - - .diff-btn-group - %label - = check_box_tag nil, 1, false, class: "js-toggle-diff-line-wrap" - Wrap text - - = link_to "#", class: "js-toggle-diff-comments btn btn-small" do - %i.icon-chevron-down - Diff comments - - - - if @merge_request && @merge_request.source_project - = link_to project_edit_tree_path(@merge_request.source_project, tree_join(@merge_request.source_branch, diff.new_path), from_merge_request_id: @merge_request.id), { class: 'btn btn-small' } do - Edit - - - = view_file_btn(@commit.id, diff, project) - - .diff-content - -# Skipp all non non-supported blobs - - return unless file.respond_to?('text?') - - if file.text? - - if params[:view] == 'parallel' - = render "projects/commits/parallel_view", diff: diff, project: project, file: file, index: i - - else - = render "projects/commits/text_file", diff: diff, index: i - - elsif file.image? - - old_file = project.repository.prev_blob_for_diff(@commit, diff) - = render "projects/commits/image", diff: diff, old_file: old_file, file: file, index: i - - else - .nothing-here-block No preview for this file type - diff --git a/app/views/projects/commits/_parallel_view.html.haml b/app/views/projects/commits/_parallel_view.html.haml deleted file mode 100644 index 80f5be98f2f..00000000000 --- a/app/views/projects/commits/_parallel_view.html.haml +++ /dev/null @@ -1,38 +0,0 @@ -/ Side-by-side diff view -- old_lines, new_lines = parallel_diff_lines(project, @commit, diff, file) -- num_lines = old_lines.length - -%div.text-file - %table - - num_lines.times do |index| - - new_line = new_lines[index] - - old_line = old_lines[index] - %tr.line_holder.parallel - -# For old line - - if old_line.type == :file_created - %td.old_line= old_line.num - %td.line_content.parallel= "File was created" - - elsif old_line.type == :deleted - %td.old_line.old= old_line.num - %td.line_content{class: "parallel noteable_line old #{old_line.code}", "line_code" => old_line.code}= old_line.content - - else old_line.type == :no_change - %td.old_line= old_line.num - %td.line_content.parallel= old_line.content - - -# For new line - - if new_line.type == :file_deleted - %td.new_line= new_line.num - %td.line_content.parallel= "File was deleted" - - elsif new_line.type == :added - %td.new_line.new= new_line.num - %td.line_content{class: "parallel noteable_line new #{new_line.code}", "line_code" => new_line.code}= new_line.content - - else new_line.type == :no_change - %td.new_line= new_line.num - %td.line_content.parallel= new_line.content - - - if @reply_allowed - - comments1 = @line_notes.select { |n| n.line_code == old_line.code }.sort_by(&:created_at) - - comments2 = @line_notes.select { |n| n.line_code == new_line.code }.sort_by(&:created_at) - - unless comments1.empty? and comments2.empty? - = render "projects/notes/diff_notes_with_reply_parallel", notes1: comments1, notes2: comments2 - diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index aa79d08509b..45269e662cd 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -18,7 +18,7 @@ - else %ul.well-list= render Commit.decorate(@commits), project: @project - = render "projects/commits/diffs", diffs: @diffs, project: @project + = render "projects/diffs/diffs", diffs: @diffs, project: @project - else .light-well diff --git a/app/views/projects/commits/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml index 17efa8debe1..334ea1ba82f 100644 --- a/app/views/projects/commits/_diffs.html.haml +++ b/app/views/projects/diffs/_diffs.html.haml @@ -1,6 +1,6 @@ .row .col-md-8 - = render 'projects/commits/diff_stats', diffs: diffs + = render 'projects/diffs/stats', diffs: diffs .col-md-4 %ul.nav.nav-tabs %li.pull-right{class: params[:view] == 'parallel' ? 'active' : ''} @@ -11,16 +11,17 @@ - params_copy[:view] = 'inline' = link_to "Inline Diff", url_for(params_copy), {id: "commit-diff-viewtype"} -- if show_diff_size_warninig?(diffs) - = render 'projects/commits/diff_warning', diffs: diffs + +- if show_diff_size_warning?(diffs) + = render 'projects/diffs/warning', diffs: diffs .files - - safe_diff_files(diffs).each_with_index do |diff, i| - = render 'projects/commits/diff_file', diff: diff, i: i, project: project + - safe_diff_files(diffs).each_with_index do |diff_file, index| + = render 'projects/diffs/file', diff_file: diff_file, i: index, project: project - if @diff_timeout .alert.alert-danger %h4 Failed to collect changes %p - Maybe diff is really big and operation failed with timeout. Try to get diff localy + Maybe diff is really big and operation failed with timeout. Try to get diff locally diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml new file mode 100644 index 00000000000..f2a8d148cc6 --- /dev/null +++ b/app/views/projects/diffs/_file.html.haml @@ -0,0 +1,48 @@ +- blob = project.repository.blob_for_diff(@commit, diff_file.diff) +- return unless blob +- blob_diff_path = diff_project_blob_path(project, tree_join(@commit.id, diff_file.file_path)) +.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }} + .diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"} + - if diff_file.deleted_file + %span= diff_file.old_path + + .diff-btn-group + - if @commit.parent_ids.present? + = view_file_btn(@commit.parent_id, diff_file, project) + - else + %span= diff_file.new_path + - if diff_file.mode_changed? + %span.file-mode= "#{diff.a_mode} → #{diff.b_mode}" + + .diff-btn-group + - unless params[:view] == 'parallel' + %label + = check_box_tag nil, 1, false, class: "js-toggle-diff-line-wrap" + Wrap text + + = link_to "#", class: "js-toggle-diff-comments btn btn-small" do + %i.icon-chevron-down + Diff comments + + + - if @merge_request && @merge_request.source_project + = link_to project_edit_tree_path(@merge_request.source_project, tree_join(@merge_request.source_branch, diff_file.new_path), from_merge_request_id: @merge_request.id), { class: 'btn btn-small' } do + Edit + + + = view_file_btn(@commit.id, diff_file, project) + + .diff-content + -# Skipp all non non-supported blobs + - return unless blob.respond_to?('text?') + - if blob.text? + - if params[:view] == 'parallel' + = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i + - else + = render "projects/diffs/text_file", diff_file: diff_file, index: i + - elsif blob.image? + - old_file = project.repository.prev_blob_for_diff(@commit, diff_file) + = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i + - else + .nothing-here-block No preview for this file type + diff --git a/app/views/projects/commits/_image.html.haml b/app/views/projects/diffs/_image.html.haml index 6d9ef5964d9..900646dd0a4 100644 --- a/app/views/projects/commits/_image.html.haml +++ b/app/views/projects/diffs/_image.html.haml @@ -1,3 +1,4 @@ +- diff = diff_file.diff - if diff.renamed_file || diff.new_file || diff.deleted_file .image %span.wrap diff --git a/app/views/projects/commits/diffs/_match_line.html.haml b/app/views/projects/diffs/_match_line.html.haml index 4ebe3379733..4ebe3379733 100644 --- a/app/views/projects/commits/diffs/_match_line.html.haml +++ b/app/views/projects/diffs/_match_line.html.haml diff --git a/app/views/projects/diffs/_match_line_parallel.html.haml b/app/views/projects/diffs/_match_line_parallel.html.haml new file mode 100644 index 00000000000..815df16aa4a --- /dev/null +++ b/app/views/projects/diffs/_match_line_parallel.html.haml @@ -0,0 +1,4 @@ +%td.old_line + %td.line_content.parallel.matched= line +%td.new_line + %td.line_content.parallel.matched= line diff --git a/app/views/projects/diffs/_parallel_view.html.haml b/app/views/projects/diffs/_parallel_view.html.haml new file mode 100644 index 00000000000..3ec769e0b83 --- /dev/null +++ b/app/views/projects/diffs/_parallel_view.html.haml @@ -0,0 +1,27 @@ +/ Side-by-side diff view +%div.text-file.diff-wrap-lines + %table + - parallel_diff(diff_file, index).each do |line| + - type_left = line[0] + - line_number_left = line[1] + - line_content_left = line[2] + - line_code = line[3] + - type_right = line[4] + - line_number_right = line[5] + - line_content_right = line[6] + + %tr.line_holder.parallel{id: line_code} + - if type_left == 'match' + = render "projects/diffs/match_line_parallel", { line: line_content_left, + line_old: line_number_left, line_new: line_number_right } + - elsif type_left == 'old' || type_left.nil? + %td.old_line{class: "#{type_left}"} + = link_to raw(line_number_left), "##{line_code}", id: line_code + %td.line_content{class: "parallel noteable_line #{type_left} #{line_code}", "line_code" => line_code }= raw line_content_left + %td.new_line{ class: "#{type_right == 'new' ? 'new' : nil}", data: { linenumber: line_number_right }} + = link_to raw(line_number_right), "##{line_code}", id: line_code + %td.line_content.parallel{class: "noteable_line #{type_right == 'new' ? 'new' : nil} #{line_code}", "line_code" => line_code}= raw line_content_right + +- if diff_file.diff.diff.blank? && diff_file.mode_changed? + .file-mode-changed + File mode changed diff --git a/app/views/projects/commits/_diff_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 8ef7cc6e086..8ef7cc6e086 100644 --- a/app/views/projects/commits/_diff_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml diff --git a/app/views/projects/commits/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml index 756481c1b21..b1c987563f1 100644 --- a/app/views/projects/commits/_text_file.html.haml +++ b/app/views/projects/diffs/_text_file.html.haml @@ -1,33 +1,36 @@ -- too_big = diff.diff.lines.count > Commit::DIFF_SAFE_LINES +- too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES - if too_big %a.supp_diff_link Changes suppressed. Click to show %table.text-file{class: "#{'hide' if too_big}"} - last_line = 0 - - each_diff_line(diff, index) do |line, type, line_code, line_new, line_old, raw_line| - - last_line = line_new + - diff_file.diff_lines.each_with_index do |line, index| + - type = line.type + - last_line = line.new_pos + - line_code = generate_line_code(diff_file.file_path, line) + - line_old = line.old_pos %tr.line_holder{ id: line_code, class: "#{type}" } - if type == "match" - = render "projects/commits/diffs/match_line", {line: line, - line_old: line_old, line_new: line_new, bottom: false} + = render "projects/diffs/match_line", {line: line.text, + line_old: line_old, line_new: line.new_pos, bottom: false} - else %td.old_line = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - if @comments_allowed = link_to_new_diff_note(line_code) - %td.new_line{data: {linenumber: line_new}} - = link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line) + %td.new_line{data: {linenumber: line.new_pos}} + = link_to raw(type == "old" ? " " : line.new_pos) , "##{line_code}", id: line_code + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line.text) - if @reply_allowed - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at) - unless comments.empty? - = render "projects/notes/diff_notes_with_reply", notes: comments, line: line + = render "projects/notes/diff_notes_with_reply", notes: comments, line: line.text - if last_line > 0 - = render "projects/commits/diffs/match_line", {line: "", + = render "projects/diffs/match_line", {line: "", line_old: last_line, line_new: last_line, bottom: true} -- if diff.diff.blank? && diff_file_mode_changed?(diff) +- if diff_file.diff.blank? && diff_file.mode_changed? .file-mode-changed File mode changed diff --git a/app/views/projects/commits/_diff_warning.html.haml b/app/views/projects/diffs/_warning.html.haml index 05d516efa11..86ed6bbeaa2 100644 --- a/app/views/projects/commits/_diff_warning.html.haml +++ b/app/views/projects/diffs/_warning.html.haml @@ -14,6 +14,6 @@ = link_to "Email patch", project_merge_request_path(@project, @merge_request, format: :patch), class: "btn btn-warning btn-small" %p To preserve performance only - %strong #{safe_diff_files(diffs).size} of #{diffs.size} + %strong #{allowed_diff_size} of #{diffs.size} files displayed. diff --git a/app/views/projects/edit_tree/_diff.html.haml b/app/views/projects/edit_tree/_diff.html.haml deleted file mode 100644 index cf044feb9a4..00000000000 --- a/app/views/projects/edit_tree/_diff.html.haml +++ /dev/null @@ -1,13 +0,0 @@ -%table.text-file - - each_diff_line(diff, 1) do |line, type, line_code, line_new, line_old, raw_line| - %tr.line_holder{ id: line_code, class: "#{type}" } - - if type == "match" - %td.old_line= "..." - %td.new_line= "..." - %td.line_content.matched= line - - else - %td.old_line - = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line) - diff --git a/app/views/projects/edit_tree/preview.html.haml b/app/views/projects/edit_tree/preview.html.haml index 87ce5dc31d3..e7c3460ad78 100644 --- a/app/views/projects/edit_tree/preview.html.haml +++ b/app/views/projects/edit_tree/preview.html.haml @@ -9,18 +9,17 @@ = raw render_markup(@blob.name, @content) - else .file-content.code - - unless @diff.empty? + - unless @diff_lines.empty? %table.text-file - - @diff.each do |line, type, line_code, line_new, line_old, raw_line| - %tr.line_holder{ id: line_code, class: "#{type}" } - - if type == "match" + - @diff_lines.each do |line| + %tr.line_holder{ class: "#{line.type}" } + - if line.type == "match" %td.old_line= "..." %td.new_line= "..." - %td.line_content.matched= line + %td.line_content.matched= line.text - else %td.old_line - = link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code - %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line) + %td.new_line + %td.line_content{class: "#{line.type}"}= raw diff_line_content(line.text) - else .nothing-here-block No changes. diff --git a/app/views/projects/import.html.haml b/app/views/projects/import.html.haml index 649dd56a8d9..2b907748486 100644 --- a/app/views/projects/import.html.haml +++ b/app/views/projects/import.html.haml @@ -23,7 +23,7 @@ .col-sm-10 = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git' .bs-callout.bs-callout-info - This url must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. + This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. %br The import will time out after 4 minutes. For big repositories, use a clone/push combination. .form-actions diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index e257f317b95..1dfcd726068 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -31,7 +31,8 @@ .issue-labels - issue.labels.each do |label| - = render_colored_label(label) + = link_to project_issues_path(issue.project, label_name: label.name) do + = render_colored_label(label) .issue-actions - if can? current_user, :modify_issue, issue diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index fd0f5446b34..41532fea741 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -68,6 +68,7 @@ .issue-show-labels.pull-right - @issue.labels.each do |label| - = render_colored_label(label) + = link_to project_issues_path(@project, label_name: label.name) do + = render_colored_label(label) .voting_notes#notes= render "projects/notes/notes_with_form" diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index 06cf390fbde..2649fb55c30 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -34,4 +34,5 @@ .merge-request-labels - merge_request.labels.each do |label| - = render_colored_label(label) + = link_to project_merge_requests_path(merge_request.project, label_name: label.name) do + = render_colored_label(label) diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml index dc3f9d592f6..657a77eb758 100644 --- a/app/views/projects/merge_requests/_new_submit.html.haml +++ b/app/views/projects/merge_requests/_new_submit.html.haml @@ -21,7 +21,12 @@ .form-group .light = f.label :description, "Description" - = f.text_area :description, class: "form-control js-gfm-input markdown-area", rows: 10 + .zennable + %input#zen-toggle-comment{ tabindex: '-1', type: 'checkbox' } + .zen-backdrop + = f.text_area :description, class: 'form-control js-gfm-input markdown-area', rows: 10, placeholder: 'Leave a comment' + %label{ for: 'zen-toggle-comment', class: 'expand' } Edit in fullscreen + %label{ for: 'zen-toggle-comment', class: 'collapse' } .clearfix.hint .pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}. .pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }. @@ -75,7 +80,7 @@ %h4 Changes - if @diffs.present? - = render "projects/commits/diffs", diffs: @diffs, project: @project + = render "projects/diffs/diffs", diffs: @diffs, project: @project - elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE .bs-callout.bs-callout-danger %h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits. diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index eb63b68106e..d361c5f579a 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,5 +1,5 @@ - if @merge_request_diff.collected? - = render "projects/commits/diffs", diffs: @merge_request.diffs, project: @merge_request.source_project + = render "projects/diffs/diffs", diffs: @merge_request.diffs, project: @merge_request.source_project - elsif @merge_request_diff.empty? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} - else diff --git a/app/views/projects/merge_requests/show/_participants.html.haml b/app/views/projects/merge_requests/show/_participants.html.haml index 007c111f7fb..b709c89cec2 100644 --- a/app/views/projects/merge_requests/show/_participants.html.haml +++ b/app/views/projects/merge_requests/show/_participants.html.haml @@ -5,4 +5,5 @@ .merge-request-show-labels.pull-right - @merge_request.labels.each do |label| - = render_colored_label(label) + = link_to project_merge_requests_path(@project, label_name: label.name) do + = render_colored_label(label) diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 7efaf5a087b..949b72356d7 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -48,9 +48,9 @@ .col-sm-10 = f.text_field :import_url, class: 'form-control', placeholder: 'https://github.com/randx/six.git' .bs-callout.bs-callout-info - This url must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. + This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git. %br - The import will time out after 2 minutes. For big repositories, use a clone/push combination. + The import will time out after 4 minutes. For big repositories, use a clone/push combination. %hr .form-group diff --git a/app/views/projects/notes/_diff_note_link.html.haml b/app/views/projects/notes/_diff_note_link.html.haml deleted file mode 100644 index 377c926a204..00000000000 --- a/app/views/projects/notes/_diff_note_link.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- note = @project.notes.new(@comments_target.merge({ line_code: line_code })) -= link_to "", - "javascript:;", - class: "add-diff-note js-add-diff-note-button", - data: { noteable_type: note.noteable_type, - noteable_id: note.noteable_id, - commit_id: note.commit_id, - line_code: note.line_code, - discussion_id: note.discussion_id }, - title: "Add a comment to this line" diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index 5ebafb13f1c..66b79e5026b 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -14,7 +14,12 @@ Preview %div .note-write-holder - = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area' + .zennable + %input#zen-toggle-comment{ tabindex: '-1', type: 'checkbox' } + .zen-backdrop + = f.text_area :note, size: 255, class: 'note_text js-note-text js-gfm-input markdown-area', placeholder: 'Leave a comment' + %label{ for: 'zen-toggle-comment', class: 'expand' } Edit in fullscreen + %label{ for: 'zen-toggle-comment', class: 'collapse' } .light.clearfix .pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }} diff --git a/app/views/projects/notes/discussions/_diff.html.haml b/app/views/projects/notes/discussions/_diff.html.haml index 26c5494f466..da71220af17 100644 --- a/app/views/projects/notes/discussions/_diff.html.haml +++ b/app/views/projects/notes/discussions/_diff.html.haml @@ -11,16 +11,17 @@ %br/ .diff-content %table - - each_diff_line_near(diff, note.diff_file_index, note.line_code) do |line, type, line_code, line_new, line_old| + - note.truncated_diff_lines.each do |line| + - line_code = generate_line_code(note.file_path, line) %tr.line_holder{ id: line_code } - - if type == "match" + - if line.type == "match" %td.old_line= "..." %td.new_line= "..." - %td.line_content.matched= line + %td.line_content.matched= line.text - else - %td.old_line= raw(type == "new" ? " " : line_old) - %td.new_line= raw(type == "old" ? " " : line_new) - %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} " + %td.old_line= raw(line.type == "new" ? " " : line.old_pos) + %td.new_line= raw(line.type == "old" ? " " : line.new_pos) + %td.line_content{class: "noteable_line #{line.type} #{line_code}", "line_code" => line_code}= raw "#{line.text} " - if line_code == note.line_code = render "projects/notes/diff_notes_with_reply", notes: discussion_notes diff --git a/app/views/search/_project_filter.html.haml b/app/views/search/_project_filter.html.haml index 36947675d18..57a45c9acb6 100644 --- a/app/views/search/_project_filter.html.haml +++ b/app/views/search/_project_filter.html.haml @@ -23,3 +23,9 @@ Comments .pull-right = @search_results.notes_count + %li{class: ("active" if @scope == 'wiki_blobs')} + = link_to search_filter_path(scope: 'wiki_blobs') do + Wiki + .pull-right + = @search_results.wiki_blobs_count + diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml index f9c0a6d61ff..58bcff9dbe3 100644 --- a/app/views/search/_results.html.haml +++ b/app/views/search/_results.html.haml @@ -1,9 +1,10 @@ %h4 #{@search_results.total_count} results found - - if @project - for #{link_to @project.name_with_namespace, @project} - - elsif @group - for #{link_to @group.name, @group} + - unless @show_snippets + - if @project + for #{link_to @project.name_with_namespace, @project} + - elsif @group + for #{link_to @group.name, @group} %hr @@ -11,6 +12,8 @@ .col-sm-3 - if @project = render "project_filter" + - elsif @show_snippets + = render 'snippet_filter' - else = render "global_filter" .col-sm-9 diff --git a/app/views/search/_snippet_filter.html.haml b/app/views/search/_snippet_filter.html.haml new file mode 100644 index 00000000000..0d1984a0d78 --- /dev/null +++ b/app/views/search/_snippet_filter.html.haml @@ -0,0 +1,13 @@ +%ul.nav.nav-pills.nav-stacked.search-filter + %li{class: ("active" if @scope == 'snippet_blobs')} + = link_to search_filter_path(scope: 'snippet_blobs', snippets: true, group_id: nil, project_id: nil) do + %i.icon-code + Snippet Contents + .pull-right + = @search_results.snippet_blobs_count + %li{class: ("active" if @scope == 'snippet_titles')} + = link_to search_filter_path(scope: 'snippet_titles', snippets: true, group_id: nil, project_id: nil) do + %i.icon-book + Titles and Filenames + .pull-right + = @search_results.snippet_titles_count diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml new file mode 100644 index 00000000000..a3d909d44dc --- /dev/null +++ b/app/views/search/results/_snippet_blob.html.haml @@ -0,0 +1,65 @@ +.search-result-row + %span + = snippet_blob[:snippet_object].title + by + = link_to user_snippets_path(snippet_blob[:snippet_object].author) do + = image_tag avatar_icon(snippet_blob[:snippet_object].author_email), class: "avatar avatar-inline s16", alt: '' + = snippet_blob[:snippet_object].author_name + %span.light #{time_ago_with_tooltip(snippet_blob[:snippet_object].created_at)} + %h4.snippet-title + - snippet_path = reliable_snippet_path(snippet_blob[:snippet_object]) + = link_to snippet_path do + .file-holder + .file-title + %i.icon-file + %strong= snippet_blob[:snippet_object].file_name + %span.options + .btn-group.tree-btn-group.pull-right + - if snippet_blob[:snippet_object].author == current_user + = link_to "Edit", edit_snippet_path(snippet_blob[:snippet_object]), class: "btn btn-tiny", title: 'Edit Snippet' + = link_to "Delete", snippet_path(snippet_blob[:snippet_object]), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-tiny", title: 'Delete Snippet' + = link_to "Raw", raw_snippet_path(snippet_blob[:snippet_object]), class: "btn btn-tiny", target: "_blank" + - if gitlab_markdown?(snippet_blob[:snippet_object].file_name) + .file-content.wiki + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = preserve do + = markdown(snippet[:data]) + - else + .file-content.code + .nothing-here-block Empty file + - elsif markup?(snippet_blob[:snippet_object].file_name) + .file-content.wiki + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = render_markup(snippet_blob[:snippet_object].file_name, snippet[:data]) + - else + .file-content.code + .nothing-here-block Empty file + - else + .file-content.code + %div.highlighted-data{class: user_color_scheme_class} + .line-numbers + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + - snippet[:data].lines.to_a.size.times do |index| + - offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 + - i = index + offset + = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}" do + %i.icon-link + = i + - unless snippet == snippet_blob[:snippet_chunks].last + %a + = "." + .highlight.term + %pre + %code + - snippet_blob[:snippet_chunks].each do |snippet| + - unless snippet[:data].empty? + = snippet[:data] + - unless snippet == snippet_blob[:snippet_chunks].last + %a + = "..." + - else + .file-content.code + .nothing-here-block Empty file diff --git a/app/views/search/results/_snippet_title.html.haml b/app/views/search/results/_snippet_title.html.haml new file mode 100644 index 00000000000..84abb9293b2 --- /dev/null +++ b/app/views/search/results/_snippet_title.html.haml @@ -0,0 +1,23 @@ +.search-result-row + %h4.snippet-title.term + = link_to reliable_snippet_path(snippet_title) do + = truncate(snippet_title.title, length: 60) + - if snippet_title.private? + %span.label.label-gray + %i.icon-lock + private + %span.cgray.monospace.tiny.pull-right.term + = snippet_title.file_name + + %small.pull-right.cgray + - if snippet_title.project_id? + = link_to snippet_title.project.name_with_namespace, project_path(snippet_title.project) + + .snippet-info + = "##{snippet_title.id}" + %span + by + = link_to user_snippets_path(snippet_title.author) do + = image_tag avatar_icon(snippet_title.author_email), class: "avatar avatar-inline s16", alt: '' + = snippet_title.author_name + %span.light #{time_ago_with_tooltip(snippet_title.created_at)} diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml new file mode 100644 index 00000000000..75414d73b0c --- /dev/null +++ b/app/views/search/results/_wiki_blob.html.haml @@ -0,0 +1,9 @@ +.blob-result + .file-holder + .file-title + = link_to project_wiki_path(@project, wiki_blob.filename) do + %i.icon-file + %strong + = wiki_blob.filename + .file-content.code.term + = render 'shared/file_hljs', blob: wiki_blob, first_line_number: wiki_blob.startline diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index 8d1614bfbd4..bae57917a4c 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -9,10 +9,12 @@ = submit_tag 'Search', class: "btn btn-create" .form-group .col-sm-2 - .col-sm-10 - = render 'filter', f: f + - unless params[:snippets].eql? 'true' + .col-sm-10 + = render 'filter', f: f = hidden_field_tag :project_id, params[:project_id] = hidden_field_tag :group_id, params[:group_id] + = hidden_field_tag :snippets, params[:snippets] = hidden_field_tag :scope, params[:scope] .results.prepend-top-10 |