Commit d859d080942175082c1a0cf34d89c0eefd1a3c39

Authored by skv-headless
1 parent cd623218

Editing preview

Gemfile
... ... @@ -82,6 +82,9 @@ gem "seed-fu"
82 82 gem "redcarpet", "~> 2.2.2"
83 83 gem "github-markup"
84 84  
  85 +# Diffs
  86 +gem 'diffy', '~> 3.0.3'
  87 +
85 88 # Asciidoc to HTML
86 89 gem "asciidoctor"
87 90  
... ...
Gemfile.lock
... ... @@ -101,6 +101,7 @@ GEM
101 101 devise-async (0.8.0)
102 102 devise (>= 2.2, < 3.2)
103 103 diff-lcs (1.2.5)
  104 + diffy (3.0.3)
104 105 docile (1.1.1)
105 106 dotenv (0.9.0)
106 107 email_spec (1.5.0)
... ... @@ -574,6 +575,7 @@ DEPENDENCIES
574 575 default_value_for (~> 3.0.0)
575 576 devise (= 3.0.4)
576 577 devise-async (= 0.8.0)
  578 + diffy (~> 3.0.3)
577 579 email_spec
578 580 email_validator (~> 1.4.0)
579 581 enumerize
... ... @@ -644,7 +646,7 @@ DEPENDENCIES
644 646 simplecov
645 647 sinatra
646 648 six
647   - slack-notifier (~> 0.2.0)
  649 + slack-notifier (~> 0.3.2)
648 650 slim
649 651 spinach-rails
650 652 spring (= 1.1.1)
... ... @@ -662,4 +664,4 @@ DEPENDENCIES
662 664 unicorn (~> 4.6.3)
663 665 unicorn-worker-killer
664 666 version_sorter
665   - webmock
666 667 \ No newline at end of file
  668 + webmock
... ...
app/assets/stylesheets/generic/files.scss
... ... @@ -26,6 +26,10 @@
26 26 margin-top: -5px;
27 27 }
28 28  
  29 + .left-options {
  30 + margin-top: -3px;
  31 + }
  32 +
29 33 .file_name {
30 34 color: $style_color;
31 35 font-size: 14px;
... ...
app/controllers/projects/edit_tree_controller.rb
... ... @@ -26,6 +26,18 @@ class Projects::EditTreeController &lt; Projects::BaseTreeController
26 26 end
27 27 end
28 28  
  29 + def preview
  30 + @content = params[:content]
  31 + #FIXME workaround https://github.com/gitlabhq/gitlabhq/issues/5936
  32 + @content += "\n" if @blob.data.end_with?("\n")
  33 +
  34 + diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
  35 + include_diff_info: true)
  36 + @diff = Gitlab::DiffParser.new(diffy.diff.scan(/.*\n/))
  37 +
  38 + render layout: false
  39 + end
  40 +
29 41 private
30 42  
31 43 def blob
... ...
app/helpers/commits_helper.rb
... ... @@ -16,9 +16,10 @@ module CommitsHelper
16 16 end
17 17  
18 18 def each_diff_line(diff, index)
19   - Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old|
20   - yield(full_line, type, line_code, line_new, line_old)
21   - end
  19 + Gitlab::DiffParser.new(diff.diff.lines.to_a, diff.new_path)
  20 + .each do |full_line, type, line_code, line_new, line_old|
  21 + yield(full_line, type, line_code, line_new, line_old)
  22 + end
22 23 end
23 24  
24 25 def each_diff_line_near(diff, index, expected_line_code)
... ...
app/helpers/tree_helper.rb
... ... @@ -91,4 +91,12 @@ module TreeHelper
91 91 def leave_edit_message
92 92 "Leave edit mode?\nAll unsaved changes will be lost."
93 93 end
  94 +
  95 + def editing_preview_title(filename)
  96 + if gitlab_markdown?(filename) || markup?(filename)
  97 + 'Preview'
  98 + else
  99 + 'Diff'
  100 + end
  101 + end
94 102 end
... ...
app/models/note.rb
... ... @@ -184,9 +184,10 @@ class Note &lt; ActiveRecord::Base
184 184 return @diff_line if @diff_line
185 185  
186 186 if diff
187   - Gitlab::DiffParser.new(diff).each do |full_line, type, line_code, line_new, line_old|
188   - @diff_line = full_line if line_code == self.line_code
189   - end
  187 + Gitlab::DiffParser.new(diff.diff.lines.to_a, diff.new_path)
  188 + .each do |full_line, type, line_code, line_new, line_old|
  189 + @diff_line = full_line if line_code == self.line_code
  190 + end
190 191 end
191 192  
192 193 @diff_line
... ...
app/views/projects/edit_tree/_diff.html.haml 0 → 100644
... ... @@ -0,0 +1,13 @@
  1 +%table.text-file
  2 + - each_diff_line(diff, 1) do |line, type, line_code, line_new, line_old, raw_line|
  3 + %tr.line_holder{ id: line_code, class: "#{type}" }
  4 + - if type == "match"
  5 + %td.old_line= "..."
  6 + %td.new_line= "..."
  7 + %td.line_content.matched= line
  8 + - else
  9 + %td.old_line
  10 + = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
  11 + %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
  12 + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line)
  13 +
... ...
app/views/projects/edit_tree/preview.html.haml 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +.diff-file
  2 + .diff-content
  3 + - if gitlab_markdown?(@blob.name)
  4 + .file-content.wiki
  5 + = preserve do
  6 + = markdown(@content)
  7 + - elsif markup?(@blob.name)
  8 + .file-content.wiki
  9 + = raw GitHub::Markup.render(@blob.name, @content)
  10 + - else
  11 + .file-content.code
  12 + - unless @diff.empty?
  13 + %table.text-file
  14 + - @diff.each do |line, type, line_code, line_new, line_old, raw_line|
  15 + %tr.line_holder{ id: line_code, class: "#{type}" }
  16 + - if type == "match"
  17 + %td.old_line= "..."
  18 + %td.new_line= "..."
  19 + %td.line_content.matched= line
  20 + - else
  21 + %td.old_line
  22 + = link_to raw(type == "new" ? "&nbsp;" : line_old), "##{line_code}", id: line_code
  23 + %td.new_line= link_to raw(type == "old" ? "&nbsp;" : line_new) , "##{line_code}", id: line_code
  24 + %td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw diff_line_content(line)
  25 + - else
  26 + %p.nothing_here_message No changes.
... ...
app/views/projects/edit_tree/show.html.haml
1 1 %h3.page-title Edit mode
2 2 .file-editor
3 3 = form_tag(project_edit_tree_path(@project, @id), method: :put, class: "form-horizontal") do
4   - .file-holder
  4 + .file-holder.file
5 5 .file-title
  6 + .btn-group.js-edit-mode.left-options
  7 + = link_to 'Edit', '#editor', class: 'active hover btn btn-tiny'
  8 + = link_to editing_preview_title(@blob.name), '#preview', class: 'btn btn-tiny', 'data-preview-url' => preview_project_edit_tree_path(@project, @id)
6 9 %i.icon-file
7 10 %span.file_name
8 11 = @path
... ... @@ -13,7 +16,8 @@
13 16 .btn-group.tree-btn-group
14 17 = link_to "Cancel", @after_edit_path, class: "btn btn-tiny btn-cancel", data: { confirm: leave_edit_message }
15 18 .file-content.code
16   - %pre#editor= @blob.data
  19 + %pre.js-edit-mode-pane#editor= @blob.data
  20 + .js-edit-mode-pane#preview.hide
17 21  
18 22 .form-group.commit_message-group
19 23 = label_tag 'commit_message', class: "control-label" do
... ... @@ -45,3 +49,28 @@
45 49 $("#file-content").val(editor.getValue());
46 50 $(".file-editor form").submit();
47 51 });
  52 +
  53 + var editModePanes = $('.js-edit-mode-pane'),
  54 + editModeLinks = $('.js-edit-mode a');
  55 +
  56 + editModeLinks.click(function(event) {
  57 + event.preventDefault();
  58 +
  59 + var currentLink = $(this),
  60 + paneId = currentLink.attr('href'),
  61 + currentPane = editModePanes.filter(paneId);
  62 +
  63 + editModeLinks.removeClass('active hover');
  64 + currentLink.addClass('active hover');
  65 + editModePanes.hide();
  66 +
  67 + if (paneId == '#preview') {
  68 + $.post(currentLink.data('preview-url'), { content: editor.getValue() }, function(response) {
  69 + currentPane.empty().append(response);
  70 + currentPane.fadeIn(200);
  71 + })
  72 + } else {
  73 + currentPane.fadeIn(200);
  74 + editor.focus()
  75 + }
  76 + })
... ...
config/routes.rb
... ... @@ -187,7 +187,9 @@ Gitlab::Application.routes.draw do
187 187 resources :blob, only: [:show, :destroy], constraints: {id: /.+/}
188 188 resources :raw, only: [:show], constraints: {id: /.+/}
189 189 resources :tree, only: [:show], constraints: {id: /.+/, format: /(html|js)/ }
190   - resources :edit_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'edit'
  190 + resources :edit_tree, only: [:show, :update], constraints: { id: /.+/ }, path: 'edit' do
  191 + post :preview, on: :member
  192 + end
191 193 resources :new_tree, only: [:show, :update], constraints: {id: /.+/}, path: 'new'
192 194 resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
193 195 resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
... ...
db/schema.rb
... ... @@ -319,7 +319,6 @@ ActiveRecord::Schema.define(version: 20140414131055) do
319 319 t.integer "notification_level", default: 1, null: false
320 320 t.datetime "password_expires_at"
321 321 t.integer "created_by_id"
322   - t.datetime "last_credential_check_at"
323 322 t.string "avatar"
324 323 t.string "confirmation_token"
325 324 t.datetime "confirmed_at"
... ... @@ -327,6 +326,7 @@ ActiveRecord::Schema.define(version: 20140414131055) do
327 326 t.string "unconfirmed_email"
328 327 t.boolean "hide_no_ssh_key", default: false
329 328 t.string "website_url", default: "", null: false
  329 + t.datetime "last_credential_check_at"
330 330 end
331 331  
332 332 add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
... ...
features/project/source/browse_files.feature
... ... @@ -29,3 +29,13 @@ Feature: Project Browse files
29 29 Given I click on "Gemfile.lock" file in repo
30 30 And I click button "edit"
31 31 Then I can edit code
  32 +
  33 + @javascript
  34 + Scenario: I can see editing preview
  35 + Given I click on "Gemfile.lock" file in repo
  36 + And I click button "edit"
  37 + And I edit code
  38 + And I click link "Diff"
  39 + Then I see diff
  40 +
  41 +
... ...
features/steps/project/browse_files.rb
... ... @@ -41,6 +41,18 @@ class ProjectBrowseFiles &lt; Spinach::FeatureSteps
41 41 page.evaluate_script('editor.getValue()').should == "GitlabFileEditor"
42 42 end
43 43  
  44 + step 'I edit code' do
  45 + page.execute_script('editor.setValue("GitlabFileEditor")')
  46 + end
  47 +
  48 + step 'I click link "Diff"' do
  49 + click_link 'Diff'
  50 + end
  51 +
  52 + step 'I see diff' do
  53 + page.should have_css '.line_holder.new'
  54 + end
  55 +
44 56 step 'I click on "new file" link in repo' do
45 57 click_link 'new-file-link'
46 58 end
... ...
lib/gitlab/diff_parser.rb
... ... @@ -4,9 +4,9 @@ module Gitlab
4 4  
5 5 attr_reader :lines, :new_path
6 6  
7   - def initialize(diff)
8   - @lines = diff.diff.lines.to_a
9   - @new_path = diff.new_path
  7 + def initialize(lines, new_path = '')
  8 + @lines = lines
  9 + @new_path = new_path
10 10 end
11 11  
12 12 def each
... ... @@ -18,10 +18,7 @@ module Gitlab
18 18 lines_arr.each do |line|
19 19 raw_line = line.dup
20 20  
21   - next if line.match(/^\-\-\- \/dev\/null/)
22   - next if line.match(/^\+\+\+ \/dev\/null/)
23   - next if line.match(/^\-\-\- a/)
24   - next if line.match(/^\+\+\+ b/)
  21 + next if filename?(line)
25 22  
26 23 full_line = html_escape(line.gsub(/\n/, ''))
27 24 full_line = ::Gitlab::InlineDiff.replace_markers full_line
... ... @@ -53,8 +50,17 @@ module Gitlab
53 50 end
54 51 end
55 52  
  53 + def empty?
  54 + @lines.empty?
  55 + end
  56 +
56 57 private
57 58  
  59 + def filename?(line)
  60 + line.start_with?('--- /dev/null', '+++ /dev/null', '--- a', '+++ b',
  61 + '--- /tmp/diffy', '+++ /tmp/diffy')
  62 + end
  63 +
58 64 def identification_type(line)
59 65 if line[0] == "+"
60 66 "new"
... ...