summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeger-Jan van de Weg <zegerjan@gitlab.com>2016-04-06 09:37:46 +0200
committerZeger-Jan van de Weg <zegerjan@gitlab.com>2016-04-15 14:38:15 +0200
commit33f8b06c3925fbefd6eac38efc71eac8b787ebd7 (patch)
tree73556e330e0714897dc6facdcd579c8043561b99
parent77a24965cafba42b596039f9058e2e11a7ebc0dd (diff)
parentf76bfed9fc3e52c7b3b731dbb311b6b394d9af62 (diff)
downloadgitlab-ce-33f8b06c3925fbefd6eac38efc71eac8b787ebd7.tar.gz
Merge branch 'master' into assign-to-issuable-opener
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--CHANGELOG28
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/javascripts/gl_dropdown.js.coffee110
-rw-r--r--app/assets/javascripts/issue.js.coffee17
-rw-r--r--app/assets/javascripts/merge_request.js.coffee16
-rw-r--r--app/assets/javascripts/notes.js.coffee38
-rw-r--r--app/assets/javascripts/zen_mode.js.coffee2
-rw-r--r--app/assets/stylesheets/framework/common.scss7
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss34
-rw-r--r--app/assets/stylesheets/framework/typography.scss2
-rw-r--r--app/assets/stylesheets/framework/variables.scss6
-rw-r--r--app/assets/stylesheets/framework/zen.scss101
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss36
-rw-r--r--app/assets/stylesheets/pages/note_form.scss127
-rw-r--r--app/assets/stylesheets/pages/notes.scss26
-rw-r--r--app/assets/stylesheets/pages/projects.scss2
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/controllers/autocomplete_controller.rb5
-rw-r--r--app/controllers/projects/project_members_controller.rb11
-rw-r--r--app/controllers/projects_controller.rb3
-rw-r--r--app/helpers/selects_helper.rb2
-rw-r--r--app/services/git_push_service.rb10
-rw-r--r--app/views/projects/_md_preview.html.haml17
-rw-r--r--app/views/projects/_zen.html.haml20
-rw-r--r--app/views/projects/notes/_edit_form.html.haml7
-rw-r--r--app/views/projects/notes/_form.html.haml4
-rw-r--r--app/views/projects/notes/_hints.html.haml15
-rw-r--r--app/views/projects/notes/_notes_with_form.html.haml31
-rw-r--r--config/initializers/premailer.rb3
-rw-r--r--doc/administration/auth/ldap.md12
-rw-r--r--doc/integration/ldap.md2
-rw-r--r--doc/markdown/markdown.md8
-rw-r--r--features/steps/shared/diff_note.rb4
-rw-r--r--features/steps/shared/note.rb4
-rw-r--r--spec/controllers/autocomplete_controller_spec.rb11
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb49
-rw-r--r--spec/controllers/projects_controller_spec.rb22
-rw-r--r--spec/features/issues_spec.rb2
-rw-r--r--spec/features/notes_on_merge_requests_spec.rb4
-rw-r--r--spec/javascripts/fixtures/zen_mode.html.haml2
-rw-r--r--spec/javascripts/issue_spec.js.coffee6
-rw-r--r--spec/mailers/shared/notify.rb2
-rw-r--r--spec/services/git_push_service_spec.rb18
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