From e81f89ee5a36dcda5680a459d29256899a6f7e00 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 29 Sep 2016 15:13:25 +0100 Subject: Added CHANGELOG entry --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index ed534b825aa..83e1f82e963 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,7 @@ v 8.13.0 (unreleased) - Fix permission for setting an issue's due date - Expose expires_at field when sharing project on API - Allow the Koding integration to be configured through the API + - Added soft wrap button to repository file/blob editor - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison) - Close open merge request without source project (Katarzyna Kobierska Ula Budziszewska) - Use a ConnectionPool for Rails.cache on Sidekiq servers -- cgit v1.2.1 From 61afa65d4e5e1ea908d90e45364fbb4e0bcfeb56 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 2 Sep 2016 19:42:42 +0100 Subject: Added soft wrap logic and button to editor Added tests Added awesomeeeeee icons --- app/assets/javascripts/blob_edit/edit_blob.js | 43 ++++++++++++++ app/assets/stylesheets/pages/editor.scss | 1 + app/helpers/appearances_helper.rb | 5 +- app/views/projects/blob/_editor.html.haml | 4 ++ app/views/shared/icons/_icon_no_wrap.svg.erb | 3 + app/views/shared/icons/_icon_soft_wrap.svg.erb | 3 + .../projects/files/edit_file_soft_wrap_spec.rb | 67 ++++++++++++++++++++++ 7 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 app/views/shared/icons/_icon_no_wrap.svg.erb create mode 100644 app/views/shared/icons/_icon_soft_wrap.svg.erb create mode 100644 spec/features/projects/files/edit_file_soft_wrap_spec.rb diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index b846bab0424..8f4a2c7ae84 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -22,6 +22,7 @@ // submitted textarea })(this)); this.initModePanesAndLinks(); + this.initSoftWrap(); new BlobLicenseSelectors({ editor: this.editor }); @@ -50,6 +51,7 @@ this.$editModePanes.hide(); currentPane.fadeIn(200); if (paneId === "#preview") { + this.$toggleButton.hide(); return $.post(currentLink.data("preview-url"), { content: this.editor.getValue() }, function(response) { @@ -57,10 +59,51 @@ return currentPane.syntaxHighlight(); }); } else { + this.$toggleButton.show(); return this.editor.focus(); } }; + EditBlob.prototype.initSoftWrap = function() { + this.isExplicitySelected = false + this.$filePathInput = $('#file_path, #file_name'); + this.$toggleButton = $('.soft-wrap-toggle'); + this.$toggleText = $('span', this.$toggleButton); + this.$noWrapIcon = $('.no-wrap-icon', this.$toggleButton); + this.$softWrapIcon = $('.soft-wrap-icon', this.$toggleButton); + this.checkFilePathIsCode(); + this.$filePathInput.on('keyup', _.debounce(this.checkFilePathIsCode.bind(this), 300)); + this.$toggleButton.on('click', this.clickSoftWrapButton.bind(this)); + }; + + EditBlob.prototype.toggleSoftWrap = function(forceToggle) { + if (_.isBoolean(forceToggle)) { + this.isSoftWrapped = forceToggle; + } else { + this.isSoftWrapped = !this.isSoftWrapped; + } + if(this.isSoftWrapped) { + this.$toggleText.text('No wrap'); + this.$noWrapIcon.removeClass('hidden'); + this.$softWrapIcon.addClass('hidden'); + } else { + this.$toggleText.text('Soft wrap'); + this.$softWrapIcon.removeClass('hidden'); + this.$noWrapIcon.addClass('hidden'); + } + this.editor.getSession().setUseWrapMode(this.isSoftWrapped); + }; + + EditBlob.prototype.checkFilePathIsCode = function() { + var isNotCode = /^(.*?\.(txt|md)|[^.]*?)$/i.test(this.$filePathInput.val()); + if (!this.isExplicitySelected) this.toggleSoftWrap(isNotCode); + }; + + EditBlob.prototype.clickSoftWrapButton = function() { + if (!this.isExplicitySelected) this.isExplicitySelected = true; + this.toggleSoftWrap(); + }; + return EditBlob; })(); diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 1aa4e06d975..ffd6089c100 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -59,6 +59,7 @@ } .encoding-selector, + .soft-wrap-toggle, .license-selector, .gitignore-selector, .gitlab-ci-yml-selector { diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index de13e7a1fc2..1e8ddb9d423 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -31,9 +31,10 @@ module AppearancesHelper end end - def custom_icon(icon_name, size: 16) + def custom_icon(icon_name, opts = {}) + opts[:size] = 16 unless opts[:size] # We can't simply do the below, because there are some .erb SVGs. # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe - render "shared/icons/#{icon_name}.svg", size: size + render "shared/icons/#{icon_name}.svg", opts end end diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index 0237e152b54..f225b1be59e 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -21,6 +21,10 @@ = dropdown_tag("Choose a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } ) .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) + = button_tag class: 'soft-wrap-toggle btn', type: 'button' do + = custom_icon('icon_soft_wrap', klass: 'soft-wrap-icon') + = custom_icon('icon_no_wrap', klass: 'no-wrap-icon hidden') + %span Soft wrap .encoding-selector = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' diff --git a/app/views/shared/icons/_icon_no_wrap.svg.erb b/app/views/shared/icons/_icon_no_wrap.svg.erb new file mode 100644 index 00000000000..e4c44091ddd --- /dev/null +++ b/app/views/shared/icons/_icon_no_wrap.svg.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_icon_soft_wrap.svg.erb b/app/views/shared/icons/_icon_soft_wrap.svg.erb new file mode 100644 index 00000000000..d9613b0c3d7 --- /dev/null +++ b/app/views/shared/icons/_icon_soft_wrap.svg.erb @@ -0,0 +1,3 @@ + + + diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb new file mode 100644 index 00000000000..7ad90b4a89c --- /dev/null +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +feature 'User uses soft wrap whilst editing file', feature: true, js: true do + before do + user = create(:user) + project = create(:project) + project.team << [user, :master] + login_as user + visit namespace_project_new_blob_path(project.namespace, project, 'master', file_name: 'test_file-name') + editor = find('.file-editor.code') + editor.click + editor.send_keys 'Touch water with paw then recoil in horror chase dog then + run away chase the pig around the house eat owner\'s food, and knock + dish off table head butt cant eat out of my own dish. Cat is love, cat + is life rub face on everything poop on grasses so meow. Playing with + balls of wool flee in terror at cucumber discovered on floor run in + circles tuxedo cats always looking dapper, but attack dog, run away + and pretend to be victim so all of a sudden cat goes crazy, yet chase + laser. Make muffins sit in window and stare ooo, a bird! yum lick yarn + hanging out of own butt jump off balcony, onto stranger\'s head yet + chase laser. Purr for no reason stare at ceiling hola te quiero.'.squish + end + + let(:toggle_button) { find('.soft-wrap-toggle') } + + scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do + wrapped_content_width = get_content_width + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + toggle_button.click + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user adds a ".js" extension and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + fill_in 'file_name', with: 'test_file-name.js' + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'No wrap' + expect(get_content_width).to be < unwrapped_content_width + end + + scenario 'user clicks "No wrap" and then changes to a ".md" extension' do + wrapped_content_width = get_content_width + + toggle_button.click + expect(toggle_button).to have_content 'Soft wrap' + unwrapped_content_width = get_content_width + expect(unwrapped_content_width).to be > wrapped_content_width + + fill_in 'file_name', with: 'test_file-name.md' + expect(toggle_button).to have_content 'Soft wrap' + expect(unwrapped_content_width).to be == get_content_width + end + + def get_content_width + find('.ace_content')[:style].slice!(/width: \d+/).slice!(/\d+/) + end +end -- cgit v1.2.1 From 70f7d2446a4ba9e301d0f7151a95a52e127f2423 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 27 Sep 2016 22:08:05 +0100 Subject: Review changes Updated tests --- app/assets/javascripts/blob_edit/edit_blob.js | 38 +++------------------- app/assets/stylesheets/pages/editor.scss | 18 ++++++++++ app/helpers/appearances_helper.rb | 5 ++- app/views/projects/blob/_editor.html.haml | 9 +++-- app/views/shared/icons/_icon_no_wrap.svg | 3 ++ app/views/shared/icons/_icon_no_wrap.svg.erb | 3 -- app/views/shared/icons/_icon_soft_wrap.svg | 3 ++ app/views/shared/icons/_icon_soft_wrap.svg.erb | 3 -- .../projects/files/edit_file_soft_wrap_spec.rb | 32 ++---------------- 9 files changed, 40 insertions(+), 74 deletions(-) create mode 100644 app/views/shared/icons/_icon_no_wrap.svg delete mode 100644 app/views/shared/icons/_icon_no_wrap.svg.erb create mode 100644 app/views/shared/icons/_icon_soft_wrap.svg delete mode 100644 app/views/shared/icons/_icon_soft_wrap.svg.erb diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 8f4a2c7ae84..de6cdd851be 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -65,45 +65,17 @@ }; EditBlob.prototype.initSoftWrap = function() { - this.isExplicitySelected = false - this.$filePathInput = $('#file_path, #file_name'); + this.isSoftWrapped = false; this.$toggleButton = $('.soft-wrap-toggle'); - this.$toggleText = $('span', this.$toggleButton); - this.$noWrapIcon = $('.no-wrap-icon', this.$toggleButton); - this.$softWrapIcon = $('.soft-wrap-icon', this.$toggleButton); - this.checkFilePathIsCode(); - this.$filePathInput.on('keyup', _.debounce(this.checkFilePathIsCode.bind(this), 300)); - this.$toggleButton.on('click', this.clickSoftWrapButton.bind(this)); + this.$toggleButton.on('click', this.toggleSoftWrap.bind(this)); }; - EditBlob.prototype.toggleSoftWrap = function(forceToggle) { - if (_.isBoolean(forceToggle)) { - this.isSoftWrapped = forceToggle; - } else { - this.isSoftWrapped = !this.isSoftWrapped; - } - if(this.isSoftWrapped) { - this.$toggleText.text('No wrap'); - this.$noWrapIcon.removeClass('hidden'); - this.$softWrapIcon.addClass('hidden'); - } else { - this.$toggleText.text('Soft wrap'); - this.$softWrapIcon.removeClass('hidden'); - this.$noWrapIcon.addClass('hidden'); - } + EditBlob.prototype.toggleSoftWrap = function(e) { + this.isSoftWrapped = !this.isSoftWrapped; + this.$toggleButton.toggleClass('soft-wrap-active', this.isSoftWrapped); this.editor.getSession().setUseWrapMode(this.isSoftWrapped); }; - EditBlob.prototype.checkFilePathIsCode = function() { - var isNotCode = /^(.*?\.(txt|md)|[^.]*?)$/i.test(this.$filePathInput.val()); - if (!this.isExplicitySelected) this.toggleSoftWrap(isNotCode); - }; - - EditBlob.prototype.clickSoftWrapButton = function() { - if (!this.isExplicitySelected) this.isExplicitySelected = true; - this.toggleSoftWrap(); - }; - return EditBlob; })(); diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index ffd6089c100..e1304335271 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -68,6 +68,24 @@ font-family: $regular_font; } + .soft-wrap-toggle { + margin: 0 $btn-side-margin; + .soft-wrap { + display: block; + } + .no-wrap { + display: none; + } + &.soft-wrap-active { + .soft-wrap { + display: none; + } + .no-wrap { + display: block; + } + } + } + .gitignore-selector, .license-selector, .gitlab-ci-yml-selector { .dropdown { line-height: 21px; diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb index 1e8ddb9d423..de13e7a1fc2 100644 --- a/app/helpers/appearances_helper.rb +++ b/app/helpers/appearances_helper.rb @@ -31,10 +31,9 @@ module AppearancesHelper end end - def custom_icon(icon_name, opts = {}) - opts[:size] = 16 unless opts[:size] + def custom_icon(icon_name, size: 16) # We can't simply do the below, because there are some .erb SVGs. # File.read(Rails.root.join("app/views/shared/icons/_#{icon_name}.svg")).html_safe - render "shared/icons/#{icon_name}.svg", opts + render "shared/icons/#{icon_name}.svg", size: size end end diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml index f225b1be59e..d4f59764a70 100644 --- a/app/views/projects/blob/_editor.html.haml +++ b/app/views/projects/blob/_editor.html.haml @@ -22,9 +22,12 @@ .gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.hidden = dropdown_tag("Choose a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector', title: "Choose a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } ) = button_tag class: 'soft-wrap-toggle btn', type: 'button' do - = custom_icon('icon_soft_wrap', klass: 'soft-wrap-icon') - = custom_icon('icon_no_wrap', klass: 'no-wrap-icon hidden') - %span Soft wrap + %span.no-wrap + = custom_icon('icon_no_wrap') + No wrap + %span.soft-wrap + = custom_icon('icon_soft_wrap') + Soft wrap .encoding-selector = select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2' diff --git a/app/views/shared/icons/_icon_no_wrap.svg b/app/views/shared/icons/_icon_no_wrap.svg new file mode 100644 index 00000000000..fe34cada002 --- /dev/null +++ b/app/views/shared/icons/_icon_no_wrap.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_icon_no_wrap.svg.erb b/app/views/shared/icons/_icon_no_wrap.svg.erb deleted file mode 100644 index e4c44091ddd..00000000000 --- a/app/views/shared/icons/_icon_no_wrap.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/app/views/shared/icons/_icon_soft_wrap.svg b/app/views/shared/icons/_icon_soft_wrap.svg new file mode 100644 index 00000000000..ea27a2024b1 --- /dev/null +++ b/app/views/shared/icons/_icon_soft_wrap.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/views/shared/icons/_icon_soft_wrap.svg.erb b/app/views/shared/icons/_icon_soft_wrap.svg.erb deleted file mode 100644 index d9613b0c3d7..00000000000 --- a/app/views/shared/icons/_icon_soft_wrap.svg.erb +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/spec/features/projects/files/edit_file_soft_wrap_spec.rb b/spec/features/projects/files/edit_file_soft_wrap_spec.rb index 7ad90b4a89c..012befa7990 100644 --- a/spec/features/projects/files/edit_file_soft_wrap_spec.rb +++ b/spec/features/projects/files/edit_file_soft_wrap_spec.rb @@ -23,42 +23,16 @@ feature 'User uses soft wrap whilst editing file', feature: true, js: true do let(:toggle_button) { find('.soft-wrap-toggle') } - scenario 'user clicks the "No wrap" button and then "Soft wrap" button' do + scenario 'user clicks the "Soft wrap" button and then "No wrap" button' do wrapped_content_width = get_content_width - toggle_button.click - expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - toggle_button.click expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user adds a ".js" extension and then changes to a ".md" extension' do - wrapped_content_width = get_content_width - - fill_in 'file_name', with: 'test_file-name.js' - expect(toggle_button).to have_content 'Soft wrap' unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'No wrap' - expect(get_content_width).to be < unwrapped_content_width - end - - scenario 'user clicks "No wrap" and then changes to a ".md" extension' do - wrapped_content_width = get_content_width + expect(unwrapped_content_width).to be < wrapped_content_width toggle_button.click expect(toggle_button).to have_content 'Soft wrap' - unwrapped_content_width = get_content_width - expect(unwrapped_content_width).to be > wrapped_content_width - - fill_in 'file_name', with: 'test_file-name.md' - expect(toggle_button).to have_content 'Soft wrap' - expect(unwrapped_content_width).to be == get_content_width + expect(get_content_width).to be > unwrapped_content_width end def get_content_width -- cgit v1.2.1