diff options
author | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-04-06 09:37:46 +0200 |
---|---|---|
committer | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-04-15 14:38:15 +0200 |
commit | 33f8b06c3925fbefd6eac38efc71eac8b787ebd7 (patch) | |
tree | 73556e330e0714897dc6facdcd579c8043561b99 | |
parent | 77a24965cafba42b596039f9058e2e11a7ebc0dd (diff) | |
parent | f76bfed9fc3e52c7b3b731dbb311b6b394d9af62 (diff) | |
download | gitlab-ce-33f8b06c3925fbefd6eac38efc71eac8b787ebd7.tar.gz |
Merge branch 'master' into assign-to-issuable-opener
44 files changed, 507 insertions, 326 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53f115c92c8..336ceb31021 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -158,8 +158,7 @@ bundler:audit: only: - master script: - - "bundle exec bundle-audit update" - - "bundle exec bundle-audit check --ignore OSVDB-115941" + - "bundle exec bundle-audit check --update --ignore OSVDB-115941" tags: - ruby - mysql diff --git a/CHANGELOG b/CHANGELOG index 9b69f447852..ca13102f37b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,11 +3,12 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.7.0 (unreleased) - All images in discussions and wikis now link to their source files !3464 (Connor Shea). - Improved Markdown rendering performance !3389 (Yorick Peterse) - - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan hu) + - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu) - Preserve time notes/comments have been updated at when moving issue - Make HTTP(s) label consistent on clone bar (Stan Hu) - Expose label description in API (Mariusz Jachimowicz) - Allow back dating on issues when created through the API + - Fix Error 500 after renaming a project path (Stan Hu) - Fix avatar stretching by providing a cropping feature - Add endpoints to archive or unarchive a project !3372 - Add links to CI setup documentation from project settings and builds pages @@ -15,16 +16,16 @@ v 8.7.0 (unreleased) - Add default scope to projects to exclude projects pending deletion - Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.) - Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.) - - Allow issues and merge requests to be assigned to the author - -v 8.6.2 (unreleased) - - Comments on confidential issues don't show up in activity feed to non-members - - Fix NoMethodError when visiting CI root path at `/ci` + - Allow issues and merge requests to be assigned to the author !2765 - Gracefully handle notes on deleted commits in merge requests (Stan Hu) - Fix creation of merge requests for orphaned branches (Stan Hu) - Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla) - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) - Improved UX of the navigation sidebar + - Build status notifications + +v 8.6.5 (unreleased) + - Check permissions when user attempts to import members from another project v 8.6.4 - Don't attempt to fetch any tags from a forked repo (Stan Hu) @@ -144,6 +145,9 @@ v 8.6.0 - Trigger a todo for mentions on commits page - Let project owners and admins soft delete issues and merge requests +v 8.5.9 + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + v 8.5.8 - Bump Git version requirement to 2.7.4 @@ -285,6 +289,12 @@ v 8.5.0 - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) - Add Todos +v 8.4.7 + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + +v 8.4.6 + - Bump Git version requirement to 2.7.4 + v 8.4.5 - No CE-specific changes @@ -398,6 +408,12 @@ v 8.4.0 - Add IP check against DNSBLs at account sign-up - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching +v 8.3.6 + - Don't attempt to fetch any tags from a forked repo (Stan Hu). + +v 8.3.5 + - Bump Git version requirement to 2.7.4 + v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/Gemfile.lock b/Gemfile.lock index 229089f431d..0981c3195a0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,7 +99,7 @@ GEM bullet (5.0.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.9.0) - bundler-audit (0.4.0) + bundler-audit (0.5.0) bundler (~> 1.2) thor (~> 0.18) byebug (8.2.1) diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 4f032a82e58..2a4811b8763 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -1,5 +1,6 @@ class GitLabDropdownFilter BLUR_KEYCODES = [27, 40] + ARROW_KEY_CODES = [38, 40] HAS_VALUE_CLASS = "has-value" constructor: (@input, @options) -> @@ -22,19 +23,23 @@ class GitLabDropdownFilter # Key events timeout = "" @input.on "keyup", (e) => + keyCode = e.which + + return if ARROW_KEY_CODES.indexOf(keyCode) >= 0 + if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.addClass HAS_VALUE_CLASS else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.removeClass HAS_VALUE_CLASS - if e.keyCode is 13 and @input.val() isnt "" + if keyCode is 13 and @input.val() isnt "" if @options.enterCallback @options.enterCallback() return clearTimeout timeout timeout = setTimeout => - blur_field = @shouldBlur e.keyCode + blur_field = @shouldBlur keyCode search_text = @input.val() if blur_field and @filterInputBlur @@ -96,6 +101,7 @@ class GitLabDropdown LOADING_CLASS = "is-loading" PAGE_TWO_CLASS = "is-page-two" ACTIVE_CLASS = "is-active" + currentIndex = -1 FILTER_INPUT = '.dropdown-input .dropdown-input-field' @@ -145,11 +151,11 @@ class GitLabDropdown data: => return @fullData callback: (data) => + currentIndex = -1 @parseData data - @highlightRow 1 enterCallback: => if @enterCallback - @selectFirstRow() + @selectRowAtIndex 0 # Event listeners @@ -218,6 +224,8 @@ class GitLabDropdown return true opened: => + @addArrowKeyEvent() + contentHtml = $('.dropdown-content', @dropdown).html() if @remote && contentHtml is "" @remote.execute() @@ -228,6 +236,7 @@ class GitLabDropdown @dropdown.trigger('shown.gl.dropdown') hidden: (e) => + @removeArrayKeyEvent() if @options.filterable @dropdown .find(".dropdown-input-field") @@ -307,11 +316,11 @@ class GitLabDropdown if @highlight text = @highlightTextMatches(text, @filterInput.val()) - html = "<li>" - html += "<a href='#{url}' class='#{cssClass}'>" - html += text - html += "</a>" - html += "</li>" + html = "<li> + <a href='#{url}' class='#{cssClass}'> + #{text} + </a> + </li>" return html @@ -322,11 +331,11 @@ class GitLabDropdown ).join('') noResults: -> - html = "<li>" - html += "<a class='dropdown-menu-empty-link is-focused'>" - html += "No matching results." - html += "</a>" - html += "</li>" + html = "<li class='dropdown-menu-empty-link'> + <a href='#' class='is-focused'> + No matching results. + </a> + </li>" highlightRow: (index) -> if @filterInput.val() isnt "" @@ -378,16 +387,81 @@ class GitLabDropdown return selectedObject - selectFirstRow: -> - selector = '.dropdown-content li:first-child a' + selectRowAtIndex: (index) -> + selector = ".dropdown-content li:not(.divider):eq(#{index}) a" + if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one .dropdown-content li:first-child a" + selector = ".dropdown-page-one #{selector}" # simulate a click on the first link $(selector).trigger "click" + addArrowKeyEvent: -> + ARROW_KEY_CODES = [38, 40] + $input = @dropdown.find(".dropdown-input-field") + + selector = '.dropdown-content li:not(.divider)' + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one #{selector}" + + $('body').on 'keydown', (e) => + currentKeyCode = e.which + + if ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0 + e.preventDefault() + e.stopImmediatePropagation() + + PREV_INDEX = currentIndex + $listItems = $(selector, @dropdown) + + # if @options.filterable + # $input.blur() + + if currentKeyCode is 40 + # Move down + currentIndex += 1 if currentIndex < ($listItems.length - 1) + else if currentKeyCode is 38 + # Move up + currentIndex -= 1 if currentIndex > 0 + + @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX + + return false + + if currentKeyCode is 13 + @selectRowAtIndex currentIndex + + removeArrayKeyEvent: -> + $('body').off 'keydown' + + highlightRowAtIndex: ($listItems, index) -> + # Remove the class for the previously focused row + $('.is-focused', @dropdown).removeClass 'is-focused' + + # Update the class for the row at the specific index + $listItem = $listItems.eq(index) + $listItem.find('a:first-child').addClass "is-focused" + + # Dropdown content scroll area + $dropdownContent = $listItem.closest('.dropdown-content') + dropdownScrollTop = $dropdownContent.scrollTop() + dropdownContentHeight = $dropdownContent.outerHeight() + dropdownContentTop = $dropdownContent.prop('offsetTop') + dropdownContentBottom = dropdownContentTop + dropdownContentHeight + + # Get the offset bottom of the list item + listItemHeight = $listItem.outerHeight() + listItemTop = $listItem.prop('offsetTop') + listItemBottom = listItemTop + listItemHeight + + if listItemBottom > dropdownContentBottom + dropdownScrollTop + # Scroll the dropdown content down + $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom) + else if listItemTop < dropdownContentTop + dropdownScrollTop + # Scroll the dropdown content up + $dropdownContent.scrollTop(listItemTop - dropdownContentTop) + $.fn.glDropdown = (opts) -> return @.each -> if (!$.data @, 'glDropdown') $.data(@, 'glDropdown', new GitLabDropdown @, opts) - diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee index d663e34871c..946d83b7bdd 100644 --- a/app/assets/javascripts/issue.js.coffee +++ b/app/assets/javascripts/issue.js.coffee @@ -6,25 +6,10 @@ class @Issue constructor: -> # Prevent duplicate event bindings @disableTaskList() - @fixAffixScroll() if $('a.btn-close').length @initTaskList() @initIssueBtnEventListeners() - fixAffixScroll: -> - fixAffix = -> - $discussion = $('.issuable-discussion') - $sidebar = $('.issuable-sidebar') - if $sidebar.hasClass('no-affix') - $sidebar.removeClass(['affix-top','affix']) - discussionHeight = $discussion.height() - sidebarHeight = $sidebar.height() - if sidebarHeight > discussionHeight - $discussion.height(sidebarHeight + 50) - $sidebar.addClass('no-affix') - $(window).on('resize', fixAffix) - fixAffix() - initTaskList: -> $('.detail-page-description .js-task-list-container').taskList('enable') $(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList @@ -49,7 +34,7 @@ class @Issue issueStatus = if isClose then 'close' else 'open' new Flash(issueFailMessage, 'alert') success: (data, textStatus, jqXHR) -> - if data.saved + if 'id' of data $(document).trigger('issuable:change'); if isClose $('a.btn-close').addClass('hidden') diff --git a/app/assets/javascripts/merge_request.js.coffee b/app/assets/javascripts/merge_request.js.coffee index 6af5a48a0bb..1f46e331427 100644 --- a/app/assets/javascripts/merge_request.js.coffee +++ b/app/assets/javascripts/merge_request.js.coffee @@ -15,8 +15,6 @@ class @MergeRequest this.$('.show-all-commits').on 'click', => this.showAllCommits() - @fixAffixScroll(); - @initTabs() # Prevent duplicate event bindings @@ -30,20 +28,6 @@ class @MergeRequest $: (selector) -> this.$el.find(selector) - fixAffixScroll: -> - fixAffix = -> - $discussion = $('.issuable-discussion') - $sidebar = $('.issuable-sidebar') - if $sidebar.hasClass('no-affix') - $sidebar.removeClass(['affix-top','affix']) - discussionHeight = $discussion.height() - sidebarHeight = $sidebar.height() - if sidebarHeight > discussionHeight - $discussion.height(sidebarHeight + 50) - $sidebar.addClass('no-affix') - $(window).on('resize', fixAffix) - fixAffix() - initTabs: -> if @opts.action != 'new' # `MergeRequests#new` has no tab-persisting or lazy-loading behavior diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee index ff06c57f2b5..86e3b860fcb 100644 --- a/app/assets/javascripts/notes.js.coffee +++ b/app/assets/javascripts/notes.js.coffee @@ -251,13 +251,11 @@ class @Notes Sets some hidden fields in the form. ### setupMainTargetNoteForm: -> - # find the form form = $(".js-new-note-form") - # insert the form after the button - form.clone().replaceAll $(".js-main-target-form") - form = form.prev("form") + # Set a global clone of the form for later cloning + @formClone = form.clone() # show the form @setupNoteForm(form) @@ -266,9 +264,7 @@ class @Notes form.removeClass "js-new-note-form" form.addClass "js-main-target-form" - # remove unnecessary fields and buttons form.find("#note_line_code").remove() - form.find(".js-close-discussion-note-form").remove() ### General note form setup. @@ -297,7 +293,14 @@ class @Notes else previewButton.removeClass("turn-on").addClass "turn-off" + textarea.on 'focus', -> + $(this).closest('.md-area').addClass 'is-focused' + + textarea.on 'blur', -> + $(this).closest('.md-area').removeClass 'is-focused' + autosize(textarea) + new Autosave textarea, [ "Note" form.find("#note_commit_id").val() @@ -307,7 +310,6 @@ class @Notes ] # remove notify commit author checkbox for non-commit notes - form.find(".js-notify-commit-author").remove() if form.find("#note_noteable_type").val() isnt "Commit" GitLab.GfmAutoComplete.setup() new DropzoneInput(form) form.show() @@ -455,15 +457,15 @@ class @Notes Shows the note form below the notes. ### replyToDiscussionNote: (e) => - form = $(".js-new-note-form") + form = @formClone.clone() replyLink = $(e.target).closest(".js-discussion-reply-button") replyLink.hide() # insert the form after the button - form.clone().insertAfter replyLink + replyLink.after form # show the form - @setupDiscussionNoteForm(replyLink, replyLink.next("form")) + @setupDiscussionNoteForm(replyLink, form) ### Shows the diff or discussion form and does some setup on it. @@ -488,7 +490,9 @@ class @Notes .text(form.find('.js-close-discussion-note-form').data('cancel-text')) @setupNoteForm form form.find(".js-note-text").focus() - form.addClass "js-discussion-note-form" + form + .removeClass('js-main-target-form') + .addClass("discussion-form js-discussion-note-form") ### Called when clicking on the "add a comment" button on the side of a diff line. @@ -498,9 +502,8 @@ class @Notes ### addDiffNote: (e) => e.preventDefault() - link = e.currentTarget - form = $(".js-new-note-form") - row = $(link).closest("tr") + $link = $(e.currentTarget) + row = $link.closest("tr") nextRow = row.next() hasNotes = nextRow.is(".notes_holder") addForm = false @@ -509,7 +512,7 @@ class @Notes # In parallel view, look inside the correct left/right pane if @isParallelView() - lineType = $(link).data("lineType") + lineType = $link.data("lineType") targetContent += "." + lineType rowCssToAdd = "<tr class=\"notes_holder js-temp-notes-holder\"><td class=\"notes_line\"></td><td class=\"notes_content parallel old\"></td><td class=\"notes_line\"></td><td class=\"notes_content parallel new\"></td></tr>" @@ -531,11 +534,11 @@ class @Notes addForm = true if addForm - newForm = form.clone() + newForm = @formClone.clone() newForm.appendTo row.next().find(targetContent) # show the form - @setupDiscussionNoteForm $(link), newForm + @setupDiscussionNoteForm $link, newForm ### Called in response to "cancel" on a diff note form. @@ -560,7 +563,6 @@ class @Notes cancelDiscussionForm: (e) => e.preventDefault() - form = $(".js-new-note-form") form = $(e.target).closest(".js-discussion-note-form") @removeDiscussionNoteForm(form) diff --git a/app/assets/javascripts/zen_mode.js.coffee b/app/assets/javascripts/zen_mode.js.coffee index e1c5446eaac..99f35ecfb0f 100644 --- a/app/assets/javascripts/zen_mode.js.coffee +++ b/app/assets/javascripts/zen_mode.js.coffee @@ -42,7 +42,7 @@ class @ZenMode $(e.currentTarget).trigger('zen_mode:leave') $(document).on 'zen_mode:enter', (e) => - @enter(e.target.parentNode) + @enter($(e.target).closest('.md-area').find('.zen-backdrop')) $(document).on 'zen_mode:leave', (e) => @exit() diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index db1a8b1bf78..2ade341c9dd 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -125,13 +125,6 @@ p.time { height: 150px; } -// Fixes alignment on notes. -.new_note { - label { - text-align: left; - } -} - // Fix issue with notes & lists creating a bunch of bottom borders. li.note { img { max-width: 100% } diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index 8328aac4e7a..ea8e1c902cb 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -1,9 +1,7 @@ .div-dropzone-wrapper { .div-dropzone { position: relative; - padding: 0; - border: 0; - margin-bottom: 5px; + margin-bottom: -5px; .div-dropzone-focus { border-color: #66afe9 !important; @@ -25,12 +23,10 @@ .div-dropzone-spinner { position: absolute; - top: 100%; - left: 100%; - margin-top: -1.1em; - margin-left: -1.1em; + bottom: 10px; + right: 5px; opacity: 0; - font-size: 30px; + font-size: 20px; transition: opacity 200ms ease-in-out; } @@ -65,17 +61,29 @@ position: relative; } +.md-header { + .nav-links { + .active { + a { + border-bottom-color: #000; + } + } + + a { + padding-top: 0; + line-height: 1; + } + } +} + .referenced-users { color: #4c4e54; padding-top: 10px; } .md-preview-holder { - background: #fff; - border: 1px solid #ddd; - min-height: 169px; - padding: 5px; - box-shadow: none; + min-height: 167px; + padding: 10px 0; } .markdown-area { diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index c3c7bc9fdbe..7b2aada5a0d 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -250,7 +250,7 @@ a > code { * Textareas intended for GFM * */ -textarea.js-gfm-input { +.js-gfm-input { font-family: $monospace_font; color: $gl-text-color; } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 98fe794d362..c2defd31884 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -217,3 +217,9 @@ $notes-light-color: #8e8e8e; $notes-action-color: #c3c3c3; $notes-role-color: #8e8e8e; $notes-role-border-color: #e4e4e4; + +$note-disabled-comment-color: #b2b2b2; +$note-form-border-color: #e5e5e5; +$note-toolbar-color: #959494; + +$zen-control-hover-color: #111; diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss index 02e24ec7c4d..f870ea0d87f 100644 --- a/app/assets/stylesheets/framework/zen.scss +++ b/app/assets/stylesheets/framework/zen.scss @@ -1,61 +1,62 @@ -.zennable { - a.js-zen-enter { - color: $gl-gray; - position: absolute; +.zen-backdrop { + &.fullscreen { + background-color: white; + position: fixed; top: 0; - right: 4px; - line-height: 56px; - } + bottom: 0; + left: 0; + right: 0; + z-index: 1031; - a.js-zen-leave { - display: none; - color: $gl-text-color; - position: absolute; - top: 10px; - right: 10px; - padding: 5px; - font-size: 36px; + 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; + } - &:hover { - color: #111; + .zen-control-leave { + display: block; + position: absolute; + top: 0; } } +} - .zen-backdrop { - &.fullscreen { - background-color: white; - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 1031; +.zen-cotrol { + padding: 0; + color: #555; + background: none; + border: 0; +} - 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-control-full { + color: $note-toolbar-color; - a.js-zen-enter { - display: none; - } + &:hover { + color: $gl-link-color; + text-decoration: none; + } +} - a.js-zen-leave { - display: block; - position: absolute; - top: 0; - } - } +.zen-control-leave { + display: none; + color: $gl-text-color; + position: absolute; + right: 10px; + padding: 5px; + font-size: 36px; + + &:hover { + color: $zen-control-hover-color; } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 7ff63ca20b6..1c6a4208974 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -195,42 +195,6 @@ line-height: 31px; } -.disabled-comment-area { - padding: 16px 0; - - .disabled-profile { - width: 40px; - height: 40px; - background: $border-gray-dark; - border-radius: 20px; - display: inline-block; - margin-right: 10px; - } - - .disabled-comment { - background: $gray-light; - display: inline-block; - vertical-align: top; - height: 200px; - border-radius: 4px; - border: 1px solid $border-gray-normal; - padding-top: 90px; - text-align: center; - right: 20px; - position: absolute; - left: 70px; - margin-bottom: 20px; - - span { - color: #b2b2b2; - - a { - color: $md-link-color; - } - } - } -} - .builds { .table-holder { overflow-x: scroll; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 655f88b0c2c..a909776b437 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -1,10 +1,6 @@ /** * Note Form */ - -.comment-btn { - @extend .btn-create; -} .reply-btn { @extend .btn-primary; margin: 10px $gl-padding; @@ -17,16 +13,17 @@ } .diff-file, .discussion { - .new_note { + .new-note { margin: 0; border: none; } } -.new_note { + +.new-note { display: none; } -.new_note, .note-edit-form { +.new-note, .note-edit-form { .note-form-actions { margin-top: $gl-padding; } @@ -40,21 +37,18 @@ img { max-width: 100%; } +} - .note_text { - width: 100%; - } +.note-textarea { + padding: 10px 0; + font-family: $regular_font; + border: 0; - .comment-hints { - margin-top: -12px; + &:focus { + outline: 0; } } -/* loading indicator */ -.notes-busy { - margin: 18px; -} - .note-image-attach { @extend .col-md-4; margin-left: 45px; @@ -62,38 +56,29 @@ } .common-note-form { - margin: 0; - background: #fff; - padding: $gl-padding; - margin-left: -$gl-padding; - margin-right: -$gl-padding; - margin-bottom: -$gl-padding; -} - -.note-form-actions { - .note-form-option { - margin-top: 8px; - margin-left: 30px; - @extend .pull-left; - } - - .js-notify-commit-author { - float: left; - } - - .write-preview-btn { - // makes the "absolute" position for links relative to this - position: relative; - - // preview/edit buttons - > a { - position: absolute; - right: 5px; - top: 8px; + .md-area { + padding: $gl-padding-top $gl-padding; + border: 1px solid $note-form-border-color; + border-radius: $border-radius-base; + + &.is-focused { + border-color: $focus-border-color; + box-shadow: 0 0 2px rgba(#000, .2), + 0 0 4px rgba($focus-border-color, .4); + + .comment-toolbar, + .nav-links { + border-color: $focus-border-color; + } } } } +.discussion-form { + padding: $gl-padding-top $gl-padding; + background-color: #fff; +} + .note-edit-form { display: none; font-size: 15px; @@ -152,11 +137,49 @@ } } -.comment-hints { - color: #999; - background: #fff; - padding: 7px; - margin-top: -7px; - border: 1px solid $border-color; - font-size: 13px; +.comment-toolbar { + padding-top: $gl-padding-top; + color: $note-toolbar-color; + border-top: 1px solid $border-color; +} + +.toolbar-button { + padding: 0; + background: none; + border: 0; + font-size: 14px; + line-height: 16px; + + &:hover, + &:focus { + color: $gl-link-color; + outline: 0; + } + + @media (min-width: $screen-md-min) { + float: left; + margin-right: $gl-padding; + + &:last-child { + float: right; + margin-right: 0; + } + } +} + +.toolbar-button-icon { + position: relative; + top: 1px; + margin-right: 3px; + color: inherit; + font-size: 16px; +} + +.toolbar-text { + font-size: 14px; + line-height: 16px; + + @media (min-width: $screen-md-min) { + float: left; + } } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 92fcaaeeacf..614ca48b901 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -20,6 +20,12 @@ ul.notes { .timeline-content { margin-left: 55px; + + &.timeline-content-form { + @media (max-width: $screen-sm-max) { + margin-left: 0; + } + } } .note-created-ago, .note-updated-at { @@ -149,7 +155,7 @@ ul.notes { &.notes_content { background-color: #fff; border-width: 1px 0; - padding-top: 0; + padding: 0; vertical-align: top; &.parallel { border-width: 1px; @@ -281,3 +287,21 @@ ul.notes { } } } + +.disabled-comment { + margin-left: -$gl-padding-top; + margin-right: -$gl-padding-top; + background-color: $gray-light; + border-radius: $border-radius-base; + border: 1px solid $border-gray-normal; + color: $note-disabled-comment-color; + line-height: 200px; + + .disabled-comment-text { + line-height: normal; + } + + a { + color: $gl-link-color; + } +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 4e6aa8cd1a6..a0ac06008b6 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -401,7 +401,7 @@ pre.light-well { } .commit_short_id { - margin-right: 5px; + margin: 0 5px; color: $gl-link-color; font-weight: 600; } diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index 5e5e38a0ba6..dbb6daf0d70 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -1,4 +1,4 @@ -.container-fluid .content { +.container-fluid { .ci-status { padding: 2px 7px; margin-right: 5px; diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index e595b233e30..eb0abc80ab4 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -15,8 +15,9 @@ class AutocompleteController < ApplicationController @users = [*@users, current_user] end - if params[:author_id] && params[:author_id] != "false" - @users = [User.find(params[:author_id]), *@users] + if params[:author_id].present? + author = User.find_by_id(params[:author_id]) + @users = [author, *@users] if author end @users.uniq! diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb index e7bddc4a6f1..e457db2f0b7 100644 --- a/app/controllers/projects/project_members_controller.rb +++ b/app/controllers/projects/project_members_controller.rb @@ -94,9 +94,14 @@ class Projects::ProjectMembersController < Projects::ApplicationController end def apply_import - giver = Project.find(params[:source_project_id]) - status = @project.team.import(giver, current_user) - notice = status ? "Successfully imported" : "Import failed" + source_project = Project.find(params[:source_project_id]) + + if can?(current_user, :read_project_member, source_project) + status = @project.team.import(source_project, current_user) + notice = status ? "Successfully imported" : "Import failed" + else + return render_404 + end redirect_to(namespace_project_project_members_path(project.namespace, project), notice: notice) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 8c3a74c8236..3cc37e59855 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -40,6 +40,9 @@ class ProjectsController < Projects::ApplicationController def update status = ::Projects::UpdateService.new(@project, current_user, project_params).execute + # Refresh the repo in case anything changed + @repository = project.repository + respond_to do |format| if status flash[:notice] = "Project '#{@project.name}' was successfully updated." diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index 368762b8265..4fc6de59a8b 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -11,7 +11,7 @@ module SelectsHelper email_user = opts[:email_user] || false first_user = opts[:first_user] && current_user ? current_user.username : false current_user = opts[:current_user] || false - author_id = opts[:author_id] || false + author_id = opts[:author_id] || '' project = opts[:project] || @project html = { diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb index c007d648dd6..36c9ee92da1 100644 --- a/app/services/git_push_service.rb +++ b/app/services/git_push_service.rb @@ -43,17 +43,21 @@ class GitPushService < BaseService @push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev]) process_commit_messages end - # Checks if the main language has changed in the project and if so - # it updates it accordingly - update_main_language # Update merge requests that may be affected by this push. A new branch # could cause the last commit of a merge request to change. update_merge_requests + # Checks if the main language has changed in the project and if so + # it updates it accordingly + update_main_language + perform_housekeeping end def update_main_language + return unless is_default_branch? + return unless push_to_new_branch? || push_to_existing_branch? + current_language = @project.repository.main_language unless current_language == @project.main_language diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml index 1fb37ef6621..4920910fee1 100644 --- a/app/views/projects/_md_preview.html.haml +++ b/app/views/projects/_md_preview.html.haml @@ -1,18 +1,19 @@ .md-area - .md-header.clearfix + .md-header %ul.nav-links %li.active - %a.js-md-write-button(href="#md-write-holder" tabindex="-1") + %a.js-md-write-button{ href: "#md-write-holder" } Write %li - %a.js-md-preview-button(href="#md-preview-holder" tabindex="-1") + %a.js-md-preview-button{ href: "#md-preview-holder" } Preview + %li.pull-right + %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button' } + Go full screen - %div - .md-write-holder - = yield - .md.md-preview-holder.hide - .js-md-preview{class: (preview_class if defined?(preview_class))} + .md-write-holder + = yield + .md.md-preview-holder.js-md-preview.hide{class: (preview_class if defined?(preview_class))} - if defined?(referenced_users) && referenced_users %div.referenced-users.hide diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index e701253d7de..bddff5cdcbc 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -1,12 +1,8 @@ -.zennable - .zen-backdrop - - classes << ' js-gfm-input js-autosize markdown-area' - - if defined?(f) && f - = f.text_area attr, class: classes - - else - = text_area_tag attr, nil, class: classes - %a.js-zen-enter(tabindex="-1" href="#") - = icon('expand') - Edit in fullscreen - %a.js-zen-leave(tabindex="-1" href="#") - = icon('compress') +.zen-backdrop + - classes << ' js-gfm-input js-autosize markdown-area' + - if defined?(f) && f + = f.text_area attr, class: classes, placeholder: "Write a comment or drag your files here..." + - else + = text_area_tag attr, nil, class: classes, placeholder: "Write a comment or drag your files here..." + %a.zen-cotrol.zen-control-leave.js-zen-leave{ href: "#" } + = icon('compress') diff --git a/app/views/projects/notes/_edit_form.html.haml b/app/views/projects/notes/_edit_form.html.haml index 2999befffc6..23e4f93eab5 100644 --- a/app/views/projects/notes/_edit_form.html.haml +++ b/app/views/projects/notes/_edit_form.html.haml @@ -1,10 +1,11 @@ .note-edit-form - = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true, html: { class: 'edit-note js-quick-submit' } do |f| + = form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true, html: { class: 'edit-note common-note-form js-quick-submit' } do |f| = note_target_fields(note) = render layout: 'projects/md_preview', locals: { preview_class: 'md-preview' } do - = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field' + = render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text js-task-list-field' = render 'projects/notes/hints' .note-form-actions.clearfix = f.submit 'Save Comment', class: 'btn btn-nr btn-save btn-grouped js-comment-button' - = link_to 'Cancel', '#', class: 'btn btn-nr btn-cancel note-edit-cancel' + %button.btn.btn-nr.btn-cancel.note-edit-cancel{ type: 'button' } + Cancel diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml index f675f092da1..c446ecec2c3 100644 --- a/app/views/projects/notes/_form.html.haml +++ b/app/views/projects/notes/_form.html.haml @@ -1,4 +1,4 @@ -= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form js-quick-submit common-note-form gfm-form" }, authenticity_token: true do |f| += form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new-note js-new-note-form js-quick-submit common-note-form gfm-form" }, authenticity_token: true do |f| = hidden_field_tag :view, diff_view = hidden_field_tag :line_type = note_target_fields(@note) @@ -8,7 +8,7 @@ = f.hidden_field :noteable_type = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do - = render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text' + = render 'projects/zen', f: f, attr: :note, classes: 'note-textarea js-note-text' = render 'projects/notes/hints' .error-alert diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml index 6e7929bdab0..0b002043408 100644 --- a/app/views/projects/notes/_hints.html.haml +++ b/app/views/projects/notes/_hints.html.haml @@ -1,9 +1,8 @@ -.comment-hints.clearfix - .pull-left +.comment-toolbar.clearfix + .toolbar-text + Styling with = link_to 'Markdown', help_page_path('markdown', 'markdown'), target: '_blank', tabindex: -1 - tip: - = random_markdown_tip - .pull-right - = link_to '#', class: 'markdown-selector', tabindex: -1 do - = icon('paperclip') - Attach a file + is supported + %button.toolbar-button.markdown-selector{ type: 'button', tabindex: '-1' } + = icon('file-image-o', class: 'toolbar-button-icon') + Attach a file diff --git a/app/views/projects/notes/_notes_with_form.html.haml b/app/views/projects/notes/_notes_with_form.html.haml index 910eb6cf66e..cc42aab5c52 100644 --- a/app/views/projects/notes/_notes_with_form.html.haml +++ b/app/views/projects/notes/_notes_with_form.html.haml @@ -1,20 +1,21 @@ %ul#notes-list.notes.main-notes-list.timeline = render "projects/notes/notes" -.js-notes-busy - -.js-main-target-form -- if can? current_user, :create_note, @project - = render "projects/notes/form", view: diff_view -- else - .disabled-comment-area - .disabled-profile - .disabled-comment - %span - Please - = link_to "register",new_user_session_path - or - = link_to "login",new_user_session_path - to post a comment +%ul.notes.timeline + %li.timeline-entry + - if can? current_user, :create_note, @project + .timeline-icon.hidden-xs.hidden-sm + %a.author_link{ href: user_path(current_user) } + = image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40' + .timeline-content.timeline-content-form + = render "projects/notes/form", view: diff_view + - else + .disabled-comment.text-center + .disabled-comment-text.inline + Please + = link_to "register",new_user_session_path + or + = link_to "login",new_user_session_path + to post a comment :javascript var notes = new Notes("#{namespace_project_notes_path(namespace_id: @project.namespace, target_id: @noteable.id, target_type: @noteable.class.name.underscore)}", #{@notes.map(&:id).to_json}, #{Time.now.to_i}, "#{diff_view}") diff --git a/config/initializers/premailer.rb b/config/initializers/premailer.rb index a44316bc3a4..b9176688bc4 100644 --- a/config/initializers/premailer.rb +++ b/config/initializers/premailer.rb @@ -3,5 +3,6 @@ Premailer::Rails.config.merge!( generate_text_part: false, preserve_styles: true, remove_comments: true, - remove_ids: true + remove_ids: true, + remove_scripts: false ) diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md index 237700bbcd9..10096779844 100644 --- a/doc/administration/auth/ldap.md +++ b/doc/administration/auth/ldap.md @@ -261,13 +261,13 @@ tree and traverse it. - Run the following check command to make sure that the LDAP settings are correct and GitLab can see your users: - ```bash - # For Omnibus installations - sudo gitlab-rake gitlab:ldap:check + ```bash + # For Omnibus installations + sudo gitlab-rake gitlab:ldap:check - # For installations from source - sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production - ``` + # For installations from source + sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production + ``` ### Connection Refused diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md index fb20308c49c..30f0c15dacc 100644 --- a/doc/integration/ldap.md +++ b/doc/integration/ldap.md @@ -1,3 +1,3 @@ # GitLab LDAP integration -This document was moved under [`administration/auth/ldap`](administration/auth/ldap.md). +This document was moved under [`administration/auth/ldap`](../administration/auth/ldap.md). diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md index e6eb1cf3819..4f199b6af6f 100644 --- a/doc/markdown/markdown.md +++ b/doc/markdown/markdown.md @@ -31,7 +31,7 @@ _GitLab uses the [Redcarpet Ruby library][redcarpet] for Markdown processing._ -For GitLab we developed something we call "GitLab Flavored Markdown" (GFM). It extends the standard Markdown in a few significant ways to add some useful functionality. +GitLab uses "GitLab Flavored Markdown" (GFM). It extends the standard Markdown in a few significant ways to add some useful functionality. It was inspired by [GitHub Flavored Markdown](https://help.github.com/articles/basic-writing-and-formatting-syntax/). You can use GFM in @@ -47,10 +47,10 @@ You can also use other rich text files in GitLab. You might have to install a de GFM honors the markdown specification in how [paragraphs and line breaks are handled](https://daringfireball.net/projects/markdown/syntax#p). -A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. +A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines. Line-breaks, or softreturns, are rendered if you end a line with two or more spaces - Roses are red [followed by two or more spaces] + Roses are red [followed by two or more spaces] Violets are blue Sugar is sweet @@ -67,7 +67,7 @@ It is not reasonable to italicize just _part_ of a word, especially when you're perform_complicated_task do_this_and_do_that_and_another_thing -perform_complicated_task +perform_complicated_task do_this_and_do_that_and_another_thing ## URL auto-linking diff --git a/features/steps/shared/diff_note.rb b/features/steps/shared/diff_note.rb index 906b66a4a63..32c3e99f450 100644 --- a/features/steps/shared/diff_note.rb +++ b/features/steps/shared/diff_note.rb @@ -125,7 +125,7 @@ module SharedDiffNote step 'I should only see one diff form' do page.within(diff_file_selector) do - expect(page).to have_css("form.new_note", count: 1) + expect(page).to have_css("form.new-note", count: 1) end end @@ -161,7 +161,7 @@ module SharedDiffNote step 'I should see a temporary diff comment form' do page.within(diff_file_selector) do - expect(page).to have_css(".js-temp-notes-holder form.new_note") + expect(page).to have_css(".js-temp-notes-holder form.new-note") end end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index fb0462d6e04..a3c3887ab46 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -2,7 +2,7 @@ module SharedNote include Spinach::DSL step 'I delete a comment' do - page.within('.notes') do + page.within('.main-notes-list') do find('.note').hover find(".js-note-delete").click end @@ -128,7 +128,7 @@ module SharedNote end step 'I edit the last comment with a +1' do - page.within(".notes") do + page.within(".main-notes-list") do find(".note").hover find('.js-note-edit').click end diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index f83c3b64f8f..28cf804c1b2 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -147,13 +147,20 @@ describe AutocompleteController do context 'author of issuable included' do before do sign_in(user) - get(:users, author_id: non_member.id) end let(:body) { JSON.parse(response.body) } - it 'should also return the author' do + it 'includes the author' do + get(:users, author_id: non_member.id) + expect(body.first["username"]).to eq non_member.username end + + it 'rejects non existent user ids' do + get(:users, author_id: 99999) + + expect(body.collect { |u| u['id'] }).not_to include(99999) + end end end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb new file mode 100644 index 00000000000..d47e4ab9a4f --- /dev/null +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -0,0 +1,49 @@ +require('spec_helper') + +describe Projects::ProjectMembersController do + let(:project) { create(:project) } + let(:another_project) { create(:project, :private) } + let(:user) { create(:user) } + let(:member) { create(:user) } + + before do + project.team << [user, :master] + another_project.team << [member, :guest] + sign_in(user) + end + + describe '#apply_import' do + shared_context 'import applied' do + before do + post(:apply_import, namespace_id: project.namespace.to_param, + project_id: project.to_param, + source_project_id: another_project.id) + end + end + + context 'when user can access source project members' do + before { another_project.team << [user, :guest] } + include_context 'import applied' + + it 'imports source project members' do + expect(project.team_members).to include member + expect(response).to set_flash.to 'Successfully imported' + expect(response).to redirect_to( + namespace_project_project_members_path(project.namespace, project) + ) + end + end + + context 'when user is not member of a source project' do + include_context 'import applied' + + it 'does not import team members' do + expect(project.team_members).to_not include member + end + + it 'responds with not found' do + expect(response.status).to eq 404 + end + end + end +end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 1893e946f5c..069cd917e5a 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -83,6 +83,28 @@ describe ProjectsController do end end + describe "#update" do + render_views + + let(:admin) { create(:admin) } + + it "sets the repository to the right path after a rename" do + new_path = 'renamed_path' + project_params = { path: new_path } + controller.instance_variable_set(:@project, project) + sign_in(admin) + + put :update, + namespace_id: project.namespace.to_param, + id: project.id, + project: project_params + + expect(project.repository.path).to include(new_path) + expect(assigns(:repository).path).to eq(project.repository.path) + expect(response.status).to eq(200) + end + end + describe "#destroy" do let(:admin) { create(:admin) } diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index db46657c36a..79000666ccc 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -22,7 +22,7 @@ describe 'Issues', feature: true do before do visit edit_namespace_project_issue_path(project.namespace, project, issue) - click_link "Edit" + click_button "Go full screen" end it 'should open new issue popup' do diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index d9a8058efd9..70d0864783d 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -152,7 +152,7 @@ describe 'Comments', feature: true do it 'has .new_note css class' do page.within('.js-temp-notes-holder') do - expect(subject).to have_css('.new_note') + expect(subject).to have_css('.new-note') end end end @@ -225,6 +225,6 @@ describe 'Comments', feature: true do end def click_diff_line(data = line_code) - page.find(%Q{button[data-line-code="#{data}"]}, visible: false).click + execute_script("$('button[data-line-code=\"#{data}\"]').click()") end end diff --git a/spec/javascripts/fixtures/zen_mode.html.haml b/spec/javascripts/fixtures/zen_mode.html.haml index 1701652c61e..cb906a7feaa 100644 --- a/spec/javascripts/fixtures/zen_mode.html.haml +++ b/spec/javascripts/fixtures/zen_mode.html.haml @@ -1,4 +1,4 @@ -.zennable +.md-area .zen-backdrop %textarea#note_note.js-gfm-input.markdown-area %a.js-zen-enter(tabindex="-1" href="#") diff --git a/spec/javascripts/issue_spec.js.coffee b/spec/javascripts/issue_spec.js.coffee index 86ba9dd8e96..ea27f36e9b5 100644 --- a/spec/javascripts/issue_spec.js.coffee +++ b/spec/javascripts/issue_spec.js.coffee @@ -29,8 +29,8 @@ describe 'reopen/close issue', -> spyOn(jQuery, 'ajax').and.callFake (req) -> expect(req.type).toBe('PUT') expect(req.url).toBe('http://gitlab.com/issues/6/close') - req.success saved: true - + req.success id: 34 + $btnClose = $('a.btn-close') $btnReopen = $('a.btn-reopen') expect($btnReopen).toBeHidden() @@ -94,7 +94,7 @@ describe 'reopen/close issue', -> spyOn(jQuery, 'ajax').and.callFake (req) -> expect(req.type).toBe('PUT') expect(req.url).toBe('http://gitlab.com/issues/6/reopen') - req.success saved: true + req.success id: 34 $btnClose = $('a.btn-close') $btnReopen = $('a.btn-reopen') diff --git a/spec/mailers/shared/notify.rb b/spec/mailers/shared/notify.rb index 56a6dbf96f9..5a85cb501dd 100644 --- a/spec/mailers/shared/notify.rb +++ b/spec/mailers/shared/notify.rb @@ -141,10 +141,12 @@ shared_examples 'a new user email' do end shared_examples 'it should have Gmail Actions links' do + it { is_expected.to have_body_text '<script type="application/ld+json">' } it { is_expected.to have_body_text /ViewAction/ } end shared_examples 'it should not have Gmail Actions links' do + it { is_expected.to_not have_body_text '<script type="application/ld+json">' } it { is_expected.to_not have_body_text /ViewAction/ } end diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 8490a729e51..1047e32960e 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -159,18 +159,28 @@ describe GitPushService, services: true do end describe "Updates main language" do - context "before push" do it { expect(project.main_language).to eq(nil) } end context "after push" do before do - @service = execute_service(project, user, @oldrev, @newrev, @ref) + @service = execute_service(project, user, @oldrev, @newrev, ref) + end + + context "to master" do + let(:ref) { @ref } + + it { expect(@service.update_main_language).to eq(true) } + it { expect(project.main_language).to eq("Ruby") } end - it { expect(@service.update_main_language).to eq(true) } - it { expect(project.main_language).to eq("Ruby") } + context "to other branch" do + let(:ref) { 'refs/heads/feature/branch' } + + it { expect(@service.update_main_language).to eq(nil) } + it { expect(project.main_language).to eq(nil) } + end end end |