summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
authorAlfredo Sumaran <alfredo@gitlab.com>2016-04-07 15:44:36 -0500
committerAlfredo Sumaran <alfredo@gitlab.com>2016-04-07 15:44:36 -0500
commit6ae6f29a2ebc4540b5b3b790b19976ab3763ed53 (patch)
treee191b2f3e11ee8f0bdbfcfcb5b4634795d66da52 /app/assets
parent8c0aba9458a25266bb52bbc2101a83ed05967722 (diff)
parent1060467bb8f1ce6886b05436d16f95996da2fa91 (diff)
downloadgitlab-ce-6ae6f29a2ebc4540b5b3b790b19976ab3763ed53.tar.gz
Merge branch 'master' into issue_14678
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/awards_handler.coffee4
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee8
-rw-r--r--app/assets/javascripts/gl_dropdown.js.coffee222
-rw-r--r--app/assets/javascripts/issue.js.coffee17
-rw-r--r--app/assets/javascripts/issues.js.coffee15
-rw-r--r--app/assets/javascripts/lib/notify.js.coffee30
-rw-r--r--app/assets/javascripts/lib/url_utility.js.coffee31
-rw-r--r--app/assets/javascripts/merge_request.js.coffee16
-rw-r--r--app/assets/javascripts/merge_request_widget.js.coffee78
-rw-r--r--app/assets/javascripts/milestone_select.js.coffee12
-rw-r--r--app/assets/javascripts/notes.js.coffee38
-rw-r--r--app/assets/javascripts/search_autocomplete.js.coffee305
-rw-r--r--app/assets/javascripts/sidebar.js.coffee1
-rw-r--r--app/assets/javascripts/zen_mode.js.coffee2
-rw-r--r--app/assets/stylesheets/behaviors.scss4
-rw-r--r--app/assets/stylesheets/framework/calendar.scss6
-rw-r--r--app/assets/stylesheets/framework/common.scss11
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss60
-rw-r--r--app/assets/stylesheets/framework/files.scss1
-rw-r--r--app/assets/stylesheets/framework/filters.scss2
-rw-r--r--app/assets/stylesheets/framework/forms.scss36
-rw-r--r--app/assets/stylesheets/framework/gitlab-theme.scss6
-rw-r--r--app/assets/stylesheets/framework/header.scss32
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss35
-rw-r--r--app/assets/stylesheets/framework/mobile.scss4
-rw-r--r--app/assets/stylesheets/framework/nav.scss14
-rw-r--r--app/assets/stylesheets/framework/selects.scss2
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss123
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap_variables.scss4
-rw-r--r--app/assets/stylesheets/framework/typography.scss8
-rw-r--r--app/assets/stylesheets/framework/variables.scss48
-rw-r--r--app/assets/stylesheets/framework/zen.scss101
-rw-r--r--app/assets/stylesheets/pages/awards.scss2
-rw-r--r--app/assets/stylesheets/pages/ci_projects.scss2
-rw-r--r--app/assets/stylesheets/pages/commit.scss8
-rw-r--r--app/assets/stylesheets/pages/commits.scss2
-rw-r--r--app/assets/stylesheets/pages/detail_page.scss8
-rw-r--r--app/assets/stylesheets/pages/diff.scss5
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/events.scss4
-rw-r--r--app/assets/stylesheets/pages/lint.scss4
-rw-r--r--app/assets/stylesheets/pages/login.scss2
-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.scss163
-rw-r--r--app/assets/stylesheets/pages/projects.scss4
-rw-r--r--app/assets/stylesheets/pages/search.scss142
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/assets/stylesheets/pages/todos.scss2
49 files changed, 1261 insertions, 530 deletions
diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee
index 47b080406d4..6a670d5e887 100644
--- a/app/assets/javascripts/awards_handler.coffee
+++ b/app/assets/javascripts/awards_handler.coffee
@@ -1,5 +1,5 @@
class @AwardsHandler
- constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
+ constructor: (@get_emojis_url, @post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
$(".js-add-award").on "click", (event) =>
event.stopPropagation()
event.preventDefault()
@@ -34,7 +34,7 @@ class @AwardsHandler
$("#emoji_search").focus()
else
$('.js-add-award').addClass "is-loading"
- $.get "/emojis", (response) =>
+ $.get @get_emojis_url, (response) =>
$('.js-add-award').removeClass "is-loading"
$(".js-award-holder").append response
setTimeout =>
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index f5e1ca9860d..70fd6f50e9c 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -146,15 +146,11 @@ class Dispatcher
when 'project_members', 'deploy_keys', 'hooks', 'services', 'protected_branches'
shortcut_handler = new ShortcutsNavigation()
-
# If we haven't installed a custom shortcut handler, install the default one
if not shortcut_handler
new Shortcuts()
initSearch: ->
- opts = $('.search-autocomplete-opts')
- path = opts.data('autocomplete-path')
- project_id = opts.data('autocomplete-project-id')
- project_ref = opts.data('autocomplete-project-ref')
- new SearchAutocomplete(path, project_id, project_ref)
+ # Only when search form is present
+ new SearchAutocomplete() if $('.search').length
diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee
index dbcad9c0514..e8d25591f63 100644
--- a/app/assets/javascripts/gl_dropdown.js.coffee
+++ b/app/assets/javascripts/gl_dropdown.js.coffee
@@ -1,8 +1,13 @@
class GitLabDropdownFilter
BLUR_KEYCODES = [27, 40]
+ ARROW_KEY_CODES = [38, 40]
HAS_VALUE_CLASS = "has-value"
constructor: (@input, @options) ->
+ {
+ @filterInputBlur = true
+ } = @options
+
$inputContainer = @input.parent()
$clearButton = $inputContainer.find('.js-dropdown-input-clear')
@@ -18,22 +23,26 @@ 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
+ if blur_field and @filterInputBlur
@input.blur()
if @options.remote
@@ -92,38 +101,61 @@ 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'
constructor: (@el, @options) ->
- self = @
@dropdown = $(@el).parent()
+
+ # Set Defaults
+ {
+ # If no input is passed create a default one
+ @filterInput = @getElement(FILTER_INPUT)
+ @highlight = false
+ @filterInputBlur = true
+ @enterCallback = true
+ } = @options
+
+ self = @
+
+ # If selector was passed
+ if _.isString(@filterInput)
+ @filterInput = @getElement(@filterInput)
+
search_fields = if @options.search then @options.search.fields else [];
if @options.data
- # Remote data
- @remote = new GitLabDropdownRemote @options.data, {
- dataType: @options.dataType,
- beforeSend: @toggleLoading.bind(@)
- success: (data) =>
- @fullData = data
+ # If data is an array
+ if _.isArray @options.data
+ @fullData = @options.data
+ @parseData @options.data
+ else
+ # Remote data
+ @remote = new GitLabDropdownRemote @options.data, {
+ dataType: @options.dataType,
+ beforeSend: @toggleLoading.bind(@)
+ success: (data) =>
+ @fullData = data
- @parseData @fullData
- }
+ @parseData @fullData
+ }
- # Init filiterable
+ # Init filterable
if @options.filterable
- @input = @dropdown.find('.dropdown-input .dropdown-input-field')
-
- @filter = new GitLabDropdownFilter @input,
+ @filter = new GitLabDropdownFilter @filterInput,
+ filterInputBlur: @filterInputBlur
remote: @options.filterRemote
query: @options.data
keys: @options.search.fields
data: =>
return @fullData
callback: (data) =>
+ currentIndex = -1
@parseData data
- @highlightRow 1
enterCallback: =>
- @selectFirstRow()
+ if @enterCallback
+ @selectRowAtIndex 0
# Event listeners
@@ -145,10 +177,15 @@ class GitLabDropdown
selector = ".dropdown-page-one .dropdown-content a"
@dropdown.on "click", selector, (e) ->
- selected = self.rowClicked $(@)
+ $el = $(@)
+ selected = self.rowClicked $el
if self.options.clicked
- self.options.clicked(selected)
+ self.options.clicked(selected, $el, e)
+
+ # Finds an element inside wrapper element
+ getElement: (selector) ->
+ @dropdown.find selector
toggleLoading: ->
$('.dropdown-menu', @dropdown).toggleClass LOADING_CLASS
@@ -188,16 +225,19 @@ class GitLabDropdown
return true
opened: =>
+ @addArrowKeyEvent()
+
contentHtml = $('.dropdown-content', @dropdown).html()
if @remote && contentHtml is ""
@remote.execute()
if @options.filterable
- @dropdown.find(".dropdown-input-field").focus()
+ @filterInput.focus()
@dropdown.trigger('shown.gl.dropdown')
hidden: (e) =>
+ @removeArrayKeyEvent()
if @options.filterable
@dropdown
.find(".dropdown-input-field")
@@ -237,13 +277,19 @@ class GitLabDropdown
renderItem: (data) ->
html = ""
+ # Divider
return "<li class='divider'></li>" if data is "divider"
+ # Separator is a full-width divider
+ return "<li class='separator'></li>" if data is "separator"
+
+ # Header
+ return "<li class='dropdown-header'>#{data.header}</li>" if data.header?
+
if @options.renderRow
# Call the render function
html = @options.renderRow(data)
else
- selected = if @options.isSelected then @options.isSelected(data) else false
if not selected
value = if @options.id then @options.id(data) else data.id
fieldName = @options.fieldName
@@ -251,35 +297,54 @@ class GitLabDropdown
if field.length
selected = true
- url = if @options.url then @options.url(data) else "#"
- text = if @options.text then @options.text(data) else ""
+ # Set URL
+ if @options.url?
+ url = @options.url(data)
+ else
+ url = if data.url? then data.url else '#'
+
+ # Set Text
+ if @options.text?
+ text = @options.text(data)
+ else
+ text = if data.text? then data.text else ''
+
cssClass = "";
if selected
cssClass = "is-active"
- html = "<li>"
- html += "<a href='#{url}' class='#{cssClass}'>"
- html += text
- html += "</a>"
- html += "</li>"
+ if @highlight
+ text = @highlightTextMatches(text, @filterInput.val())
+
+ html = "<li>
+ <a href='#{url}' class='#{cssClass}'>
+ #{text}
+ </a>
+ </li>"
return html
+ highlightTextMatches: (text, term) ->
+ occurrences = fuzzaldrinPlus.match(text, term)
+ text.split('').map((character, i) ->
+ if i in occurrences then "<b>#{character}</b>" else character
+ ).join('')
+
noResults: ->
- html = "<li>"
- html += "<a href='#' 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 @input.val() isnt ""
+ if @filterInput.val() isnt ""
selector = '.dropdown-content li:first-child a'
if @dropdown.find(".dropdown-toggle-page").length
selector = ".dropdown-page-one .dropdown-content li:first-child a"
- $(selector).addClass 'is-focused'
+ @getElement(selector).addClass 'is-focused'
rowClicked: (el) ->
fieldName = @options.fieldName
@@ -288,7 +353,7 @@ class GitLabDropdown
selectedObject = @renderedData[selectedIndex]
value = if @options.id then @options.id(selectedObject, el) else selectedObject.id
field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']")
-
+
if el.hasClass(ACTIVE_CLASS)
el.removeClass(ACTIVE_CLASS)
field.remove()
@@ -296,6 +361,8 @@ class GitLabDropdown
# Toggle the dropdown label
if @options.toggleLabel
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel
+ else
+ selectedObject
else
if !value?
field.remove()
@@ -311,24 +378,93 @@ class GitLabDropdown
if @options.toggleLabel
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject)
if value?
- if !field.length
+ if !field.length and fieldName
# Create hidden input for form
input = "<input type='hidden' name='#{fieldName}' value='#{value}' />"
if @options.inputId?
input = $(input)
.attr('id', @options.inputId)
@dropdown.before input
+ else
+ field.val value
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"
+ $(selector, @dropdown).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 ->
- new GitLabDropdown @, opts
+ 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/issues.js.coffee b/app/assets/javascripts/issues.js.coffee
index b1479bfb449..0d9f2094c2a 100644
--- a/app/assets/javascripts/issues.js.coffee
+++ b/app/assets/javascripts/issues.js.coffee
@@ -26,6 +26,20 @@
$(".selected_issue").bind "change", Issues.checkChanged
+ # Update state filters if present in page
+ updateStateFilters: ->
+ stateFilters = $('.issues-state-filters')
+ newParams = {}
+ paramKeys = ['author_id', 'label_name', 'milestone_title', 'assignee_id', 'issue_search']
+
+ for paramKey in paramKeys
+ newParams[paramKey] = gl.utils.getUrlParameter(paramKey) or ''
+
+ if stateFilters.length
+ stateFilters.find('a').each ->
+ initialUrl = $(this).attr 'href'
+ $(this).attr 'href', gl.utils.mergeUrlParams(newParams, initialUrl)
+
# Make sure we trigger ajax request only after user stop typing
initSearch: ->
@timer = null
@@ -54,6 +68,7 @@
# Change url so if user reload a page - search results are saved
history.replaceState {page: issuesUrl}, document.title, issuesUrl
Issues.reload()
+ Issues.updateStateFilters()
dataType: "json"
checkChanged: ->
diff --git a/app/assets/javascripts/lib/notify.js.coffee b/app/assets/javascripts/lib/notify.js.coffee
new file mode 100644
index 00000000000..3f9ca39912c
--- /dev/null
+++ b/app/assets/javascripts/lib/notify.js.coffee
@@ -0,0 +1,30 @@
+((w) ->
+ notificationGranted = (message, opts, onclick) ->
+ notification = new Notification(message, opts)
+
+ if onclick
+ notification.onclick = onclick
+
+ notifyPermissions = ->
+ if 'Notification' of window
+ Notification.requestPermission()
+
+ notifyMe = (message, body, icon, onclick) ->
+ opts =
+ body: body
+ icon: icon
+ # Let's check if the browser supports notifications
+ if !('Notification' of window)
+ # do nothing
+ else if Notification.permission == 'granted'
+ # If it's okay let's create a notification
+ notificationGranted message, opts, onclick
+ else if Notification.permission != 'denied'
+ Notification.requestPermission (permission) ->
+ # If the user accepts, let's create a notification
+ if permission == 'granted'
+ notificationGranted message, opts, onclick
+
+ w.notify = notifyMe
+ w.notifyPermissions = notifyPermissions
+) window
diff --git a/app/assets/javascripts/lib/url_utility.js.coffee b/app/assets/javascripts/lib/url_utility.js.coffee
new file mode 100644
index 00000000000..abd556e0b4e
--- /dev/null
+++ b/app/assets/javascripts/lib/url_utility.js.coffee
@@ -0,0 +1,31 @@
+((w) ->
+
+ w.gl ?= {}
+ w.gl.utils ?= {}
+
+ w.gl.utils.getUrlParameter = (sParam) ->
+ sPageURL = decodeURIComponent(window.location.search.substring(1))
+ sURLVariables = sPageURL.split('&')
+ sParameterName = undefined
+ i = 0
+ while i < sURLVariables.length
+ sParameterName = sURLVariables[i].split('=')
+ if sParameterName[0] is sParam
+ return if sParameterName[1] is undefined then true else sParameterName[1]
+ i++
+
+ # #
+ # @param {Object} params - url keys and value to merge
+ # @param {String} url
+ # #
+ w.gl.utils.mergeUrlParams = (params, url) ->
+ newUrl = decodeURIComponent(url)
+ for paramName, paramValue of params
+ pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
+ if url.search(pattern) >= 0
+ newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
+ else
+ newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
+ newUrl
+
+) window
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/merge_request_widget.js.coffee b/app/assets/javascripts/merge_request_widget.js.coffee
index 738ffc8343b..84a8887fbce 100644
--- a/app/assets/javascripts/merge_request_widget.js.coffee
+++ b/app/assets/javascripts/merge_request_widget.js.coffee
@@ -2,13 +2,20 @@ class @MergeRequestWidget
# Initialize MergeRequestWidget behavior
#
# check_enable - Boolean, whether to check automerge status
- # url_to_automerge_check - String, URL to use to check automerge status
- # current_status - String, current automerge status
- # ci_enable - Boolean, whether a CI service is enabled
- # url_to_ci_check - String, URL to use to check CI status
+ # merge_check_url - String, URL to use to check automerge status
+ # ci_status_url - String, URL to use to check CI status
#
+
constructor: (@opts) ->
- modal = $('#modal_merge_info').modal(show: false)
+ $('#modal_merge_info').modal(show: false)
+ @firstCICheck = true
+ @readyForCICheck = true
+ clearInterval @fetchBuildStatusInterval
+
+ @pollCIStatus()
+ notifyPermissions()
+
+ setOpts: (@opts) ->
mergeInProgress: (deleteSourceBranch = false)->
$.ajax
@@ -27,18 +34,61 @@ class @MergeRequestWidget
dataType: 'json'
getMergeStatus: ->
- $.get @opts.url_to_automerge_check, (data) ->
+ $.get @opts.merge_check_url, (data) ->
$('.mr-state-widget').replaceWith(data)
- getCiStatus: ->
- if @opts.ci_enable
- $.get @opts.url_to_ci_check, (data) =>
- this.showCiState data.status
+ ciLabelForStatus: (status) ->
+ if status == 'success'
+ 'passed'
+ else
+ status
+
+ pollCIStatus: ->
+ @fetchBuildStatusInterval = setInterval ( =>
+ return if not @readyForCICheck
+
+ @getCIStatus(true)
+
+ @readyForCICheck = false
+ ), 10000
+
+ getCIStatus: (showNotification) ->
+ _this = @
+ $('.ci-widget-fetching').show()
+
+ $.getJSON @opts.ci_status_url, (data) =>
+ @readyForCICheck = true
+
+ if @firstCICheck
+ @firstCICheck = false
+ @opts.ci_status = data.status
+
+ if @opts.ci_status is ''
+ @opts.ci_status = data.status
+ return
+
+ if data.status isnt @opts.ci_status
+ @showCIStatus data.status
if data.coverage
- this.showCiCoverage data.coverage
- , 'json'
+ @showCICoverage data.coverage
+
+ if showNotification
+ message = @opts.ci_message.replace('{{status}}', @ciLabelForStatus(data.status))
+ message = message.replace('{{sha}}', data.sha)
+ message = message.replace('{{title}}', data.title)
+
+ notify(
+ "Build #{@ciLabelForStatus(data.status)}",
+ message,
+ @opts.gitlab_icon,
+ ->
+ @close()
+ Turbolinks.visit _this.opts.builds_path
+ )
+
+ @opts.ci_status = data.status
- showCiState: (state) ->
+ showCIStatus: (state) ->
$('.ci_widget').hide()
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
if state in allowed_states
@@ -52,7 +102,7 @@ class @MergeRequestWidget
$('.ci_widget.ci-error').show()
@setMergeButtonClass('btn-danger')
- showCiCoverage: (coverage) ->
+ showCICoverage: (coverage) ->
text = 'Coverage ' + coverage + '%'
$('.ci_widget:visible .ci-coverage').text(text)
diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee
index e2a7d5fbba2..f73127f49f0 100644
--- a/app/assets/javascripts/milestone_select.js.coffee
+++ b/app/assets/javascripts/milestone_select.js.coffee
@@ -84,12 +84,16 @@ class @MilestoneSelect
# display:block overrides the hide-collapse rule
$value.removeAttr('style')
- clicked: (e) ->
+ clicked: (selected) ->
if $dropdown.hasClass 'js-filter-bulk-update'
return
- if $dropdown.hasClass 'js-filter-submit'
- $dropdown.parents('form').submit()
+ if $dropdown.hasClass('js-filter-submit')
+ if selected.name?
+ selectedMilestone = selected.name
+ else
+ selectedMilestone = ''
+ Issues.filterResults $dropdown.closest('form')
else
selected = $selectbox
.find('input[type="hidden"]')
@@ -117,4 +121,4 @@ class @MilestoneSelect
else
$value.html(milestoneLinkNoneTemplate)
$sidebarCollapsedValue.find('span').text('No')
- ) \ No newline at end of file
+ )
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/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee
index c1801365266..6a7b4ad1db7 100644
--- a/app/assets/javascripts/search_autocomplete.js.coffee
+++ b/app/assets/javascripts/search_autocomplete.js.coffee
@@ -1,11 +1,296 @@
class @SearchAutocomplete
- constructor: (search_autocomplete_path, project_id, project_ref) ->
- project_id = '' unless project_id
- project_ref = '' unless project_ref
- query = "?project_id=" + project_id + "&project_ref=" + project_ref
-
- $("#search").autocomplete
- source: search_autocomplete_path + query
- minLength: 1
- select: (event, ui) ->
- location.href = ui.item.url
+
+ KEYCODE =
+ ESCAPE: 27
+ BACKSPACE: 8
+ ENTER: 13
+
+ constructor: (opts = {}) ->
+ {
+ @wrap = $('.search')
+
+ @optsEl = @wrap.find('.search-autocomplete-opts')
+ @autocompletePath = @optsEl.data('autocomplete-path')
+ @projectId = @optsEl.data('autocomplete-project-id') || ''
+ @projectRef = @optsEl.data('autocomplete-project-ref') || ''
+
+ } = opts
+
+ # Dropdown Element
+ @dropdown = @wrap.find('.dropdown')
+ @dropdownContent = @dropdown.find('.dropdown-content')
+
+ @locationBadgeEl = @getElement('.search-location-badge')
+ @locationText = @getElement('.location-text')
+ @scopeInputEl = @getElement('#scope')
+ @searchInput = @getElement('.search-input')
+ @projectInputEl = @getElement('#search_project_id')
+ @groupInputEl = @getElement('#group_id')
+ @searchCodeInputEl = @getElement('#search_code')
+ @repositoryInputEl = @getElement('#repository_ref')
+ @clearInput = @getElement('.js-clear-input')
+
+ @saveOriginalState()
+
+ # Only when user is logged in
+ @createAutocomplete() if gon.current_user_id
+
+ @searchInput.addClass('disabled')
+
+ @saveTextLength()
+
+ @bindEvents()
+
+ # Finds an element inside wrapper element
+ getElement: (selector) ->
+ @wrap.find(selector)
+
+ saveOriginalState: ->
+ @originalState = @serializeState()
+
+ saveTextLength: ->
+ @lastTextLength = @searchInput.val().length
+
+ createAutocomplete: ->
+ @searchInput.glDropdown
+ filterInputBlur: false
+ filterable: true
+ filterRemote: true
+ highlight: true
+ enterCallback: false
+ filterInput: 'input#search'
+ search:
+ fields: ['text']
+ data: @getData.bind(@)
+ selectable: true
+ clicked: @onClick.bind(@)
+
+ getData: (term, callback) ->
+ _this = @
+
+ # Do not trigger request if input is empty
+ return if @searchInput.val() is ''
+
+ # Prevent multiple ajax calls
+ return if @loadingSuggestions
+
+ @loadingSuggestions = true
+
+ jqXHR = $.get(@autocompletePath, {
+ project_id: @projectId
+ project_ref: @projectRef
+ term: term
+ }, (response) ->
+ # Hide dropdown menu if no suggestions returns
+ if !response.length
+ _this.disableAutocomplete()
+ return
+
+ data = []
+
+ # List results
+ firstCategory = true
+ for suggestion in response
+
+ # Add group header before list each group
+ if lastCategory isnt suggestion.category
+ data.push 'separator' if !firstCategory
+
+ firstCategory = false if firstCategory
+
+ data.push
+ header: suggestion.category
+
+ lastCategory = suggestion.category
+
+ data.push
+ id: "#{suggestion.category.toLowerCase()}-#{suggestion.id}"
+ category: suggestion.category
+ text: suggestion.label
+ url: suggestion.url
+
+ # Add option to proceed with the search
+ if data.length
+ data.push('separator')
+ data.push
+ text: "Result name contains \"#{term}\""
+ url: "/search?\
+ search=#{term}\
+ &project_id=#{_this.projectInputEl.val()}\
+ &group_id=#{_this.groupInputEl.val()}"
+
+ callback(data)
+ ).always ->
+ _this.loadingSuggestions = false
+
+ serializeState: ->
+ {
+ # Search Criteria
+ search_project_id: @projectInputEl.val()
+ group_id: @groupInputEl.val()
+ search_code: @searchCodeInputEl.val()
+ repository_ref: @repositoryInputEl.val()
+ scope: @scopeInputEl.val()
+
+ # Location badge
+ _location: @locationText.text()
+ }
+
+ bindEvents: ->
+ $(document).on 'click', @onDocumentClick
+ @searchInput.on 'keydown', @onSearchInputKeyDown
+ @searchInput.on 'keyup', @onSearchInputKeyUp
+ @searchInput.on 'click', @onSearchInputClick
+ @searchInput.on 'focus', @onSearchInputFocus
+ @clearInput.on 'click', @onClearInputClick
+
+ onDocumentClick: (e) =>
+ # If clicking outside the search box
+ # And search input is not focused
+ # And we are not clicking inside a suggestion
+ if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).parents('ul').length
+ @onSearchInputBlur()
+
+ enableAutocomplete: ->
+ # No need to enable anything if user is not logged in
+ return if !gon.current_user_id
+
+ _this = @
+ @loadingSuggestions = false
+
+ @dropdown.addClass('open')
+ @searchInput.removeClass('disabled')
+
+ onSearchInputKeyDown: =>
+ # Saves last length of the entered text
+ @saveTextLength()
+
+ onSearchInputKeyUp: (e) =>
+ switch e.keyCode
+ when KEYCODE.BACKSPACE
+ # when trying to remove the location badge
+ if @lastTextLength is 0 and @badgePresent()
+ @removeLocationBadge()
+
+ # When removing the last character and no badge is present
+ if @lastTextLength is 1
+ @disableAutocomplete()
+
+ # When removing any character from existin value
+ if @lastTextLength > 1
+ @enableAutocomplete()
+
+ when KEYCODE.ESCAPE
+ @restoreOriginalState()
+
+ else
+ # Handle the case when deleting the input value other than backspace
+ # e.g. Pressing ctrl + backspace or ctrl + x
+ if @searchInput.val() is ''
+ @disableAutocomplete()
+ else
+ # We should display the menu only when input is not empty
+ @enableAutocomplete()
+
+ @wrap.toggleClass 'has-value', !!e.target.value
+
+ # Avoid falsy value to be returned
+ return
+
+ onSearchInputClick: (e) =>
+ # Prevents closing the dropdown menu
+ e.stopImmediatePropagation()
+
+ onSearchInputFocus: =>
+ @isFocused = true
+ @wrap.addClass('search-active')
+
+ onClearInputClick: (e) =>
+ e.preventDefault()
+ @searchInput.val('').focus()
+
+ onSearchInputBlur: (e) =>
+ @isFocused = false
+ @wrap.removeClass('search-active')
+
+ # If input is blank then restore state
+ if @searchInput.val() is ''
+ @restoreOriginalState()
+
+ addLocationBadge: (item) ->
+ category = if item.category? then "#{item.category}: " else ''
+ value = if item.value? then item.value else ''
+
+ html = "<span class='location-badge'>
+ <i class='location-text'>#{category}#{value}</i>
+ </span>"
+ @locationBadgeEl.html(html)
+ @wrap.addClass('has-location-badge')
+
+ restoreOriginalState: ->
+ inputs = Object.keys @originalState
+
+ for input in inputs
+ @getElement("##{input}").val(@originalState[input])
+
+
+ if @originalState._location is ''
+ @locationBadgeEl.empty()
+ else
+ @addLocationBadge(
+ value: @originalState._location
+ )
+
+ @dropdown.removeClass 'open'
+
+ badgePresent: ->
+ @locationBadgeEl.children().length
+
+ resetSearchState: ->
+ inputs = Object.keys @originalState
+
+ for input in inputs
+
+ # _location isnt a input
+ break if input is '_location'
+
+ @getElement("##{input}").val('')
+
+ removeLocationBadge: ->
+ @locationBadgeEl.empty()
+
+ # Reset state
+ @resetSearchState()
+
+ @wrap.removeClass('has-location-badge')
+
+ disableAutocomplete: ->
+ @searchInput.addClass('disabled')
+ @dropdown.removeClass('open')
+ @restoreMenu()
+
+ restoreMenu: ->
+ html = "<ul>
+ <li><a class='dropdown-menu-empty-link is-focused'>Loading...</a></li>
+ </ul>"
+ @dropdownContent.html(html)
+
+ onClick: (item, $el, e) ->
+ if location.pathname.indexOf(item.url) isnt -1
+ e.preventDefault()
+ if not @badgePresent
+ if item.category is 'Projects'
+ @projectInputEl.val(item.id)
+ @addLocationBadge(
+ value: 'This project'
+ )
+
+ if item.category is 'Groups'
+ @groupInputEl.val(item.id)
+ @addLocationBadge(
+ value: 'This group'
+ )
+
+ $el.removeClass('is-active')
+ @disableAutocomplete()
+ @searchInput.val('').focus()
diff --git a/app/assets/javascripts/sidebar.js.coffee b/app/assets/javascripts/sidebar.js.coffee
index 860d4f438d0..e1778511240 100644
--- a/app/assets/javascripts/sidebar.js.coffee
+++ b/app/assets/javascripts/sidebar.js.coffee
@@ -4,7 +4,6 @@ expanded = 'page-sidebar-expanded'
toggleSidebar = ->
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
$('header').toggleClass("header-collapsed header-expanded")
- $('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
setTimeout ( ->
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/behaviors.scss b/app/assets/stylesheets/behaviors.scss
index 469f4f296ae..542a53f0377 100644
--- a/app/assets/stylesheets/behaviors.scss
+++ b/app/assets/stylesheets/behaviors.scss
@@ -13,10 +13,10 @@
// Toggle between two states.
.js-toggler-container {
- .turn-on { display: block; }
+ .turn-on { display: block; }
.turn-off { display: none; }
&.on {
- .turn-on { display: none; }
+ .turn-on { display: none; }
.turn-off { display: block; }
}
}
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index e3192823a1a..0b3af592d4a 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,3 +1,9 @@
+.calender-block {
+ @media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
+ overflow-x: scroll;
+ }
+}
+
.user-calendar-activities {
.calendar_onclick_hr {
padding: 0;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 9b676d759e0..2ade341c9dd 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -121,17 +121,10 @@ p.time {
text-shadow: none;
}
-.thin_area{
+.thin_area {
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% }
@@ -148,7 +141,7 @@ li.note {
}
}
-.wiki_content code, .readme code{
+.wiki_content code, .readme code {
background-color: inherit;
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 6c870ed927e..82dc1acbd01 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -42,7 +42,7 @@
font-size: 15px;
text-align: left;
border: 1px solid $dropdown-toggle-border-color;
- border-radius: 2px;
+ border-radius: $dropdown-border-radius;
outline: 0;
text-overflow: ellipsis;
white-space: nowrap;
@@ -75,12 +75,12 @@
width: 240px;
margin-top: 2px;
margin-bottom: 0;
- padding: 10px;
- font-size: 14px;
+ font-size: 15px;
font-weight: normal;
+ padding: 10px 0;
background-color: $dropdown-bg;
border: 1px solid $dropdown-border-color;
- border-radius: $border-radius-base;
+ border-radius: $dropdown-border-radius;
box-shadow: 0 2px 4px $dropdown-shadow-color;
&.is-loading {
@@ -101,9 +101,17 @@
li {
text-align: left;
list-style: none;
+ padding: 0 10px;
}
.divider {
+ height: 1px;
+ margin: 8px 10px;
+ padding: 0;
+ background-color: $dropdown-divider-color;
+ }
+
+ .separator {
width: 100%;
height: 1px;
margin-top: 8px;
@@ -141,6 +149,17 @@
line-height: 16px;
}
}
+
+ .dropdown-header {
+ color: $dropdown-header-color;
+ font-size: 13px;
+ line-height: 22px;
+ padding: 0 10px 10px;
+ }
+
+ .separator + .dropdown-header {
+ padding-top: 2px;
+ }
}
.dropdown-menu-paging {
@@ -158,6 +177,10 @@
.dropdown-menu-back {
display: block;
}
+
+ .dropdown-content {
+ padding: 0 10px;
+ }
}
}
@@ -193,7 +216,7 @@
}
.dropdown-select {
- width: 300px;
+ width: $dropdown-width;
}
.dropdown-menu-align-right {
@@ -222,20 +245,11 @@
}
}
-.dropdown-header {
- padding-left: 5px;
- padding-right: 5px;
- color: $dropdown-header-color;
- font-size: 13px;
- line-height: 22px;
-}
.dropdown-title {
position: relative;
- margin-bottom: 10px;
- padding-left: 30px;
- padding-right: 30px;
- padding-bottom: 10px;
+ padding: 0 0 15px;
+ margin: 0 10px 10px;
font-weight: 600;
line-height: 1;
text-align: center;
@@ -261,21 +275,26 @@
}
.dropdown-menu-close {
- right: 0;
+ right: 7px;
+ width: 20px;
+ height: 20px;
+ top: -1px;
}
.dropdown-menu-back {
- left: 0;
+ left: 7px;
+ top: 2px;
}
.dropdown-input {
position: relative;
margin-bottom: 10px;
+ padding: 0 10px;
.fa {
position: absolute;
top: 10px;
- right: 10px;
+ right: 20px;
color: #c7c7c7;
font-size: 12px;
pointer-events: none;
@@ -285,6 +304,9 @@
display: none;
cursor: pointer;
pointer-events: all;
+ right: 22px;
+ top: 9px;
+ font-size: 14px;
}
&.has-value {
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index a26ace5cc19..b15f4e7bd5e 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -20,6 +20,7 @@
margin: 0;
text-align: left;
padding: 10px $gl-padding;
+ word-wrap: break-word;
.file-actions {
float: right;
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index b05c5df1bd8..9209347f9bc 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -3,7 +3,7 @@
vertical-align: top;
}
-@media (min-width: $screen-sm-min) {
+@media (min-width: $screen-sm-min) {
.issues-filters,
.issues_bulk_update {
.dropdown-menu-toggle {
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 4cb4129b71b..54cb5461113 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -6,40 +6,6 @@ input {
border-radius: $border-radius-base;
}
-input[type='search'] {
- background-color: white;
- padding-left: 10px;
-}
-
-input[type='search'].search-input {
- background-repeat: no-repeat;
- background-position: 10px;
- background-size: 16px;
- background-position-x: 30%;
- padding-left: 10px;
- background-color: $gray-light;
-
- &.search-input[value=""] {
- background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAFu0lEQVRIia1WTahkVxH+quqce7vf6zdvJpHoIlkYJ2SiJiIokmQjgoGgIAaEIYuYXWICgojiwkmC4taFwhjcyIDusogEIwwiSSCKPwsdwzAg0SjJ9Izzk5n3+nXfe8+pqizOvd395scfsJqi6dPnnDr11Vc/NJ1OwUTosqJLCmYCHCAC2mSHs+ojZv6AO46Y+20AhIneJsafhPhXVZSXDk7qi+aOLhtQNuBmQtcarAKjTXpn2+l3u2yPunvZSABRucjcAV/eMZuM48/Go/g1d19kc4wq+e8MZjWkbI/P5t2P3RFFbv7SQdyBlBUx8N8OTuqjMcof+N94yMPrY2DMm/ytnb32J0QrY+6AqsHM4Q64O9SKDmerKDD3Oy/tNL9vk342CC8RuU6n0ymCMHb22scu7zQngtASOjUHE1BX4UUAv4b7Ow6qiXCXuz/UdvogAAweDY943/b4cAz0ZlYHXeMsnT07RVb7wMUr8ykI4H5HVkMd5Rcb4/jNURVOL5qErAaAUUdCCIJ5kx5q2nw8m39ImEAAsjpE6PStB0YfMcd1wqqG3Xn7A3PfZyyKnNjaqD4fmE/fCNKshirIyY1xvI+Av6g5QIAIIWX7cJPssboSiBBEeKmsZne0Sb8kzAUWNYyq8NvbDo0fZ6beqxuLmqOOMr/lwOh+YXpXtbjERGja9JyZ9+HxpXKb9Gj5oywRESbj+Cj1ENG1QViTGBl1FbC1We1tbVRfHWIoQkhqH9xbpE92XUbb6VJZ1R4crjRz1JWcDMJvLdoMcyAEhjuwHo8Bfndg3mbszhOY+adVlMtD3po51OwzIQiEaams7oeJhxRw1FFOVpFRRUYIhMBAFRnjOsC8IFHHUA4TQQhgAqpAiIFfGbxkIqj54ayGbL7UoOqHCniAEKHLNr26l+D9wQJzeUwMAnfHvEnLECzZRwRV++d60ptjW9VLZeolEJG6GwCCE0CFVNB+Ay0NEqoQYG4YYFu7B8IEVRt3uRzy/osIoLV9QZimWXGHUMFdmI6M64DUF2Je88R9VZqCSP+QlcF5k+4tCzSsXaqjINuK6UyE0+s/mk6/qFq8oAIL9pqMLhkGsNrOyoOIlszust3aJv0U9+kFdwjTGwWl1YdF+KWlQSZ0Se/psj8yGVdg5tJyfH96EBWmLtoEMwMzMFt031NzGWLLzKhC+KV7H5ZeeaMOPxemma2x68puc0LN3+/u6LJiePS6MKHvn4wu6cPzJj0hsioeMfDrEvjv5r6W9gBvjKJujuKzQ0URIZj75NylvT+mbHfXQa4rwAMaVRTMm/SFyzvNy0yF6+4AM+1ubcSnqkAIUjQKl1RKSbE5jt+vovx1MBqF0WW7/d1Z80ab9BtmuJ3Xk5cJKds9TZt/uLPXvtiTrQ+dIwqfAejUvM1os6FNikXKUHfQ+ekUsXT5u85enJ0CaBSkkGEo1syUQ+DfMdE/4GA1uzupf9zdbzhOmLsF4efHVXjaHHAzmDtGdQRd/Nc5wAEJjNki3XfhyvwVNz80xANrht3LsENY9cBBdN1L9GUyyvFRFZ42t75sBvCQRykbRlU4tT2pPxoCvzx09d4GmPs200M6wKdWSDGK8mppYSWdhAlt0qeaLv+IadXU9/Evq4FAZ8ej+LmtcTxaRX4NWI0Uag5Vg1p5MYg8BnlhXIdPHDow+vTWZvVMVttXDLqkTzZdPj6Qii6cP1cSvIdl3iQkNYyi9HH0I22y+93tY3DcQkTZgQtM+POoCr8x97eylkmtrgKuztrvXJ21x/aNKuqIkZ/fntRfCdcTfhUTAIhRzoDojJD0aSNLLwMzmpT7+JaLtyf1MwDo6qz9djFaUq3t9MlFmy/c1OCSceY9fMsVaL9mvH9ocXdkdWxv1scAePG0THAhMOaLdOw/Gvxfxb1w4eCapyIENUcV5M3/u8FitAxZ25P6GAHT3UX39Srw+QOb1ZffA98Dl2Wy1BYkAAAAAElFTkSuQmCC');
- }
-
- &.search-input::-webkit-input-placeholder {
- text-align: center;
- }
-
- &.search-input:-moz-placeholder { /* Firefox 18- */
- text-align: center;
- }
-
- &.search-input::-moz-placeholder { /* Firefox 19+ */
- text-align: center;
- }
-
- &.search-input:-ms-input-placeholder {
- text-align: center;
- }
-}
-
input[type='text'].danger {
background: #f2dede!important;
border-color: #d66;
@@ -125,7 +91,7 @@ label {
}
.form-control::-webkit-input-placeholder {
- color: #7f8fa4;
+ color: $gl-placeholder-color;
}
.input-group {
diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
index c83cf881596..fa9038ebaca 100644
--- a/app/assets/stylesheets/framework/gitlab-theme.scss
+++ b/app/assets/stylesheets/framework/gitlab-theme.scss
@@ -33,10 +33,15 @@
background: $color;
}
+ .complex-sidebar .nav-primary {
+ border-right: 1px solid lighten($color, 3%);
+ }
+
.sidebar-wrapper {
background: $color-darker;
.sidebar-user {
+ border-top: 1px solid lighten($color, 3%);
background: $color-darker;
color: $color-light;
@@ -62,7 +67,6 @@
.count {
color: $color-light;
- background: $color-dark;
}
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 6a68bb5c115..724980b2208 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -36,7 +36,7 @@ header {
padding: 0;
.nav > li > a {
- color: #7f8fa4;
+ color: $gl-icon-color;
font-size: 18px;
padding: 0;
margin: ($header-height - 28) / 2 0;
@@ -62,7 +62,7 @@ header {
background-color: #eee;
}
&.active {
- color: #7f8fa4;
+ color: $gl-icon-color;
}
}
}
@@ -81,14 +81,14 @@ header {
font-size: 19px;
line-height: $header-height;
font-weight: normal;
- color: #4c4e54;
+ color: $gl-text-color;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
a {
- color: #4c4e54;
+ color: $gl-text-color;
&:hover {
text-decoration: underline;
}
@@ -117,37 +117,17 @@ header {
}
}
- .search {
- margin-right: 10px;
- margin-left: 10px;
- margin-top: ($header-height - 36) / 2;
-
- form {
- margin: 0;
- padding: 0;
- }
-
- .search-input {
- width: 220px;
-
- &:focus {
- @include box-shadow(none);
- outline: none;
- }
- }
- }
-
.impersonation i {
color: $red-normal;
}
}
@mixin collapsed-header {
- margin-left: $sidebar_collapsed_width;
+ margin-left: 40px;
}
.header-collapsed {
- margin-left: $sidebar_collapsed_width;
+ margin-left: 40px;
@media (min-width: $screen-md-min) {
@include collapsed-header;
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 8328aac4e7a..c8f86d60e3b 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,30 @@
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;
+ overflow-x: auto;
}
.markdown-area {
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index 5ea4f9a49db..66180f38a4f 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -107,7 +107,7 @@
}
.page-title {
- .note_created_ago, .new-issue-link {
+ .note-created-ago, .new-issue-link {
display: none;
}
}
@@ -116,7 +116,7 @@
display: none;
}
- aside:not(.right-sidebar){
+ aside:not(.right-sidebar) {
display: none;
}
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 95bdd6d1ea3..94f5a12ff6a 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -56,6 +56,17 @@
}
}
+ .nav-search {
+ display: inline-block;
+ width: 50%;
+ padding: 11px 0;
+
+ /* Small devices (phones, tablets, 768px and lower) */
+ @media (max-width: $screen-sm-min) {
+ width: 100%;
+ }
+ }
+
.nav-links {
display: inline-block;
width: 50%;
@@ -100,6 +111,7 @@
> form {
display: inline-block;
+ margin-top: -1px;
}
.icon-label {
@@ -110,7 +122,7 @@
height: 34px;
display: inline-block;
position: relative;
- top: 1px;
+ top: 2px;
margin-right: $gl-padding-top;
/* Medium devices (desktops, 992px and up) */
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index e82d052f45a..b2fab387e17 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -51,7 +51,7 @@
padding: 10px 15px;
}
-.select2-drop{
+.select2-drop {
color: #7f8fa4;
}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 18189e985c4..1d49249dd80 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -144,7 +144,7 @@
}
a {
- padding: 7px 15px;
+ padding: 7px 12px;
font-size: $gl-font-size;
line-height: 24px;
color: $gray;
@@ -169,10 +169,12 @@
}
.count {
- float: right;
- background: #eee;
- padding: 0 8px;
- @include border-radius(6px);
+ &:before {
+ content: '(';
+ }
+ &:after {
+ content: ')';
+ }
}
&.back-link i {
@@ -191,6 +193,27 @@
}
}
+.expand-nav a {
+ color: $gl-icon-color;
+ width: 60px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ font-size: 20px;
+ background: #fff;
+ height: 59px;
+ text-align: center;
+ line-height: 59px;
+ border-bottom: 1px solid #eee;
+ transition-duration: .3s;
+ outline: none;
+ z-index: 100;
+
+ &:hover {
+ text-decoration: none;
+ }
+}
+
.collapse-nav a {
width: $sidebar_width;
position: fixed;
@@ -210,55 +233,12 @@
}
.page-sidebar-collapsed {
- padding-left: $sidebar_collapsed_width;
-
.sidebar-wrapper {
- width: $sidebar_collapsed_width;
-
- .header-logo {
- width: $sidebar_collapsed_width;
-
- a {
- padding-left: ($sidebar_collapsed_width - 36) / 2;
-
- .gitlab-text-container {
- display: none;
- }
- }
- }
-
- .nav-sidebar {
- width: $sidebar_collapsed_width;
-
- li {
- width: auto;
-
- a {
- span {
- display: none;
- }
- }
- }
- }
-
- .collapse-nav a {
- width: $sidebar_collapsed_width;
- }
-
- .sidebar-user {
- padding-left: ($sidebar_collapsed_width - 36) / 2;
- width: $sidebar_collapsed_width;
-
- .username {
- display: none;
- }
- }
+ display: none;
}
}
.page-sidebar-expanded {
- padding-left: $sidebar_collapsed_width;
-
@media (min-width: $screen-md-min) {
padding-left: $sidebar_width;
}
@@ -309,3 +289,48 @@
padding-right: $sidebar_collapsed_width;
}
}
+
+.complex-sidebar {
+ display: inline-block;
+
+ .nav-primary {
+ width: 61px;
+ float: left;
+ height: 100vh;
+
+ .nav-sidebar {
+ width: 60px;
+
+ li a {
+ width: 60px;
+
+ span {
+ display: none;
+ }
+ }
+ }
+ }
+
+ .nav-secondary {
+ $nav-secondary-width: 168px;
+
+ float: left;
+ width: $nav-secondary-width;
+
+ .nav-sidebar {
+ width: $nav-secondary-width;
+
+ li {
+ width: $nav-secondary-width;
+
+ a {
+ width: $nav-secondary-width;
+
+ i {
+ display: none;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index f63ac033234..c72af5dad0a 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -56,8 +56,8 @@ $component-active-bg: $brand-info;
//##
$input-color: $text-color;
-$input-border: #e7e9ed;
-$input-border-focus: #7f8fa4;
+$input-border: $border-color;
+$input-border-focus: $focus-border-color;
$legend-color: $text-color;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index b1886fbe67b..7b2aada5a0d 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -138,6 +138,12 @@
}
}
+ a.no-attachment-icon {
+ &:before {
+ display: none;
+ }
+ }
+
/* Link to current header. */
h1, h2, h3, h4, h5, h6 {
position: relative;
@@ -244,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 61e0dd4d672..8d3ad934a50 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -11,6 +11,7 @@ $gutter_inner_width: 258px;
* UI elements
*/
$border-color: #efeff1;
+$focus-border-color: #3aabf0;
$table-border-color: #eef0f2;
$background-color: #faf9f9;
@@ -26,6 +27,7 @@ $gl-text-orange: #d90;
$gl-link-color: #3084bb;
$gl-dark-link-color: #333;
$gl-placeholder-color: #8f8f8f;
+$gl-icon-color: $gl-placeholder-color;
$gl-gray: $gl-text-color;
$gl-header-color: $gl-title-color;
@@ -66,7 +68,7 @@ $header-height: 58px;
$fixed-layout-width: 1280px;
$gl-avatar-size: 40px;
$error-exclamation-point: #e62958;
-$border-radius-default: 3px;
+$border-radius-default: 2px;
$btn-transparent-color: #8f8f8f;
$ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px;
@@ -102,9 +104,9 @@ $orange-light: rgba(252, 109, 38, 0.80);
$orange-normal: #e75e40;
$orange-dark: #ce5237;
-$red-light: #f06559;
-$red-normal: #e52c5a;
-$red-dark: #d22852;
+$red-light: #e52c5a;
+$red-normal: #d22852;
+$red-dark: darken($red-normal, 5%);
$border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
@@ -126,9 +128,9 @@ $border-orange-light: #fc6d26;
$border-orange-normal: #ce5237;
$border-orange-dark: #c14e35;
-$border-red-light: #f24f41;
-$border-red-normal: #d22852;
-$border-red-dark: #ca264f;
+$border-red-light: #d22852;
+$border-red-normal: #ca264f;
+$border-red-dark: darken($border-red-normal, 5%);
$help-well-bg: #fafafa;
$help-well-border: #e5e5e5;
@@ -166,6 +168,8 @@ $regular_font: 'Source Sans Pro', "Helvetica Neue", Helvetica, Arial, sans-serif
/*
* Dropdowns
*/
+$dropdown-border-radius: 2px;
+$dropdown-width: 300px;
$dropdown-bg: #fff;
$dropdown-link-color: #555;
$dropdown-link-hover-bg: $row-hover;
@@ -176,8 +180,8 @@ $dropdown-divider-color: rgba(#000, .1);
$dropdown-header-color: #959494;
$dropdown-title-btn-color: #bfbfbf;
$dropdown-input-color: #555;
-$dropdown-input-focus-border: rgb(58, 171, 240);
-$dropdown-input-focus-shadow: rgba(#000, .2);
+$dropdown-input-focus-border: $focus-border-color;
+$dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6);
$dropdown-toggle-bg: #fff;
@@ -193,3 +197,29 @@ $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
$award-emoji-menu-bg: #fff;
$award-emoji-menu-border: #f1f2f4;
$award-emoji-new-btn-icon-color: #dcdcdc;
+
+/*
+ * Search Box
+ */
+$search-input-border-color: rgba(#4688f1, .8);
+$search-input-focus-shadow-color: $dropdown-input-focus-shadow;
+$search-input-width: 244px;
+$location-badge-color: #aaa;
+$location-badge-bg: $gray-normal;
+$location-badge-active-bg: #4f91f8;
+$location-icon-color: #e7e9ed;
+$location-icon-active-color: #807e7e;
+
+/*
+ * Notes
+ */
+$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/awards.scss b/app/assets/stylesheets/pages/awards.scss
index 28994e60baa..37bf38fa65d 100644
--- a/app/assets/stylesheets/pages/awards.scss
+++ b/app/assets/stylesheets/pages/awards.scss
@@ -37,7 +37,7 @@
height: 300px;
overflow-y: scroll;
- input.emoji-search{
+ input.emoji-search {
background-image: url("data:image/png;base64,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");
background-repeat: no-repeat;
background-position: right 5px center;
diff --git a/app/assets/stylesheets/pages/ci_projects.scss b/app/assets/stylesheets/pages/ci_projects.scss
index 2a7b5cfc7fd..67a9d7d2cf7 100644
--- a/app/assets/stylesheets/pages/ci_projects.scss
+++ b/app/assets/stylesheets/pages/ci_projects.scss
@@ -42,7 +42,7 @@
}
}
- .loading{
+ .loading {
font-size: 20px;
}
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index 971656feb42..082911bd118 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -1,15 +1,15 @@
-.commit-title{
+.commit-title {
display: block;
}
-.commit-author, .commit-committer{
+.commit-author, .commit-committer {
display: block;
color: #999;
font-weight: normal;
font-style: italic;
}
-.commit-author strong, .commit-committer strong{
+.commit-author strong, .commit-committer strong {
font-weight: bold;
font-style: normal;
}
@@ -74,7 +74,7 @@
color: $gl-text-red;
}
}
- .edit-file{
+ .edit-file {
a {
color: $gl-text-color;
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index b6011fe7679..8272615768d 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -1,4 +1,4 @@
-.commits-compare-switch{
+.commits-compare-switch {
@include btn-default;
@include btn-white;
background: image-url("switch_icon.png") no-repeat center center;
diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss
index d3eda1a57e6..5917f089720 100644
--- a/app/assets/stylesheets/pages/detail_page.scss
+++ b/app/assets/stylesheets/pages/detail_page.scss
@@ -33,8 +33,12 @@
.description {
margin-top: 6px;
- p:last-child {
- margin-bottom: 0;
+ p {
+ overflow-x: auto;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
}
}
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index f1368d74b3b..939555bb260 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -59,9 +59,14 @@
border-collapse: separate;
margin: 0;
padding: 0;
+
.line_holder td {
line-height: $code_line_height;
font-size: $code_font_size;
+
+ span {
+ white-space: pre;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 43be5e38ba8..0f0592a0ab8 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -1,5 +1,5 @@
.file-editor {
- #editor{
+ #editor {
border: none;
@include border-radius(0);
height: 500px;
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 84eefd01cfe..c66efe978cd 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -43,10 +43,6 @@
.md {
color: #7f8fa4;
font-size: $gl-font-size;
-
- iframe.twitter-share-button {
- vertical-align: bottom;
- }
}
pre {
diff --git a/app/assets/stylesheets/pages/lint.scss b/app/assets/stylesheets/pages/lint.scss
index 6d2bd33b28b..6926448519e 100644
--- a/app/assets/stylesheets/pages/lint.scss
+++ b/app/assets/stylesheets/pages/lint.scss
@@ -1,9 +1,9 @@
.ci-body {
- .incorrect-syntax{
+ .incorrect-syntax {
font-size: 19px;
color: red;
}
- .correct-syntax{
+ .correct-syntax {
font-size: 19px;
color: #47a447;
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 777bcbca5c3..403171d4532 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -36,7 +36,7 @@
}
}
- .login-box{
+ .login-box {
background: #fafafa;
border-radius: 10px;
box-shadow: 0 0 2px #ccc;
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 4bd2016bdcf..aca86457c70 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -20,9 +20,15 @@ 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 {
+ .note-created-ago, .note-updated-at {
white-space: nowrap;
}
@@ -39,53 +45,6 @@ ul.notes {
}
}
- .discussion-header,
- .note-header {
- @extend .cgray;
-
- a:hover {
- text-decoration: none;
- }
-
- .avatar {
- float: left;
- margin-right: 10px;
- }
-
- .discussion-last-update,
- .note-last-update {
- &:before {
- content: "\00b7";
- }
-
- a {
- color: $gl-gray;
-
- &:hover {
- text-decoration: underline;
- }
- }
- }
- .author {
- color: #4c4e54;
- margin-right: 3px;
-
- &:hover {
- color: $gl-link-color;
- }
- }
- .author-username {
- }
-
- .note-role {
- float: right;
- margin-top: 1px;
- border: 1px solid #bbb;
- background-color: transparent;
- color: $gl-gray;
- }
- }
-
.discussion-body {
padding-top: 15px;
}
@@ -123,7 +82,7 @@ ul.notes {
// On diffs code should wrap nicely and not overflow
pre {
code {
- white-space: pre-wrap;
+ white-space: pre;
}
}
@@ -196,42 +155,90 @@ ul.notes {
&.notes_content {
background-color: #fff;
border-width: 1px 0;
- padding-top: 0;
+ padding: 0;
vertical-align: top;
- &.parallel{
+ &.parallel {
border-width: 1px;
}
}
}
}
+.discussion-header,
+.note-header {
+ a {
+ color: inherit;
+
+ &:hover {
+ color: $gl-link-color;
+ text-decoration: none;
+ }
+ }
+
+ .author_link {
+ font-weight: 600;
+ }
+}
+
+.note-headline-light,
+.discussion-headline-light {
+ color: $notes-light-color;
+}
+
/**
* Actions for Discussions/Notes
*/
-.discussion,
-.note {
- .discussion-actions,
- .note-actions {
- float: right;
- margin-left: 10px;
+.discussion-actions,
+.note-actions {
+ float: right;
+ margin-left: 10px;
+ color: $notes-action-color;
+}
- a {
- margin-left: 5px;
- color: $gl-gray;
+.note-action-button,
+.discussion-action-button {
+ display: inline-block;
+ margin-left: 10px;
+ line-height: 24px;
- i.fa {
- font-size: 16px;
- line-height: 16px;
- }
+ .fa {
+ position: relative;
+ top: 1px;
+ font-size: 17px;
+ }
- &:hover {
- @extend .cgray;
- &.danger { @extend .cred; }
- }
- }
+ .fa-trash-o {
+ top: 0;
+ font-size: 16px;
}
}
+
+.discussion-toggle-button {
+ line-height: 20px;
+ font-size: 13px;
+
+ .fa {
+ margin-right: 3px;
+ font-size: 10px;
+ line-height: 18px;
+ vertical-align: top;
+ }
+}
+
+.note-role {
+ position: relative;
+ top: -2px;
+ display: inline-block;
+ padding-left: 4px;
+ padding-right: 4px;
+ color: $notes-role-color;
+ font-size: 12px;
+ line-height: 20px;
+ border: 1px solid $notes-role-border-color;
+ border-radius: $border-radius-base;
+}
+
.diff-file .note .note-actions {
right: 0;
top: 0;
@@ -280,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..fcca9d4faf5 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -315,7 +315,7 @@ pre.light-well {
}
.git-empty {
- margin: 0 7px;
+ margin: 0 7px 7px;
h5 {
color: #5c5d5e;
@@ -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/search.scss b/app/assets/stylesheets/pages/search.scss
index b6e45024644..f0f3744c6fa 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -21,3 +21,145 @@
}
}
+.search {
+ margin-right: 10px;
+ margin-left: 10px;
+ margin-top: ($header-height - 35) / 2;
+
+ form {
+ @extend .form-control;
+ margin: 0;
+ padding: 4px;
+ width: $search-input-width;
+ line-height: 24px;
+ }
+
+ .location-text {
+ font-style: normal;
+ }
+
+ .search-input {
+ border: none;
+ font-size: 14px;
+ outline: none;
+ padding: 0;
+ margin-left: 5px;
+ line-height: 25px;
+ width: 98%;
+ }
+
+ .location-badge {
+ line-height: 25px;
+ padding: 0 5px;
+ border-radius: $border-radius-default;
+ font-size: 14px;
+ font-style: normal;
+ color: $location-badge-color;
+ display: inline-block;
+ background-color: $location-badge-bg;
+ vertical-align: top;
+ }
+
+ .search-input-container {
+ display: -webkit-flex;
+ display: flex;
+ position: relative;
+ }
+
+ .search-location-badge, .search-input-wrap {
+ // Fallback if flexbox is not supported
+ display: inline-block;
+ }
+
+ .search-input-wrap {
+ width: 100%;
+
+ .search-icon, .clear-icon {
+ position: absolute;
+ right: 5px;
+ top: 0;
+ color: $location-icon-color;
+
+ &:before {
+ font-family: FontAwesome;
+ font-weight: normal;
+ font-style: normal;
+ }
+ }
+
+ .search-icon {
+ @extend .fa-search;
+ @include transition(color .15s);
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ }
+
+ .clear-icon {
+ @extend .fa-times;
+ display: none;
+ }
+
+ // Rewrite position. Dropdown menu should be relative to .search-input-container
+ .dropdown {
+ position: static;
+ }
+
+ .dropdown-header {
+ text-transform: uppercase;
+ font-size: 11px;
+ }
+
+ // Custom dropdown positioning
+ .dropdown-menu {
+ top: 30px;
+ left: -5px;
+ padding: 0;
+
+ ul {
+ padding: 10px 0;
+ }
+ }
+
+ .dropdown-content {
+ max-height: 350px;
+ }
+ }
+
+ &.search-active {
+ form {
+ @extend .form-control:focus;
+ border-color: $dropdown-input-focus-border;
+ box-shadow: 0 0 4px $search-input-focus-shadow-color;
+ }
+
+ .location-badge {
+ @include transition(all .15s);
+ background-color: $location-badge-active-bg;
+ color: $white-light;
+ }
+
+ .search-input-wrap {
+ i {
+ color: $location-icon-active-color;
+ }
+ }
+ }
+
+ &.has-value {
+ .search-icon {
+ display: none;
+ }
+
+ .clear-icon {
+ cursor: pointer;
+ display: block;
+ }
+ }
+
+ &.has-location-badge {
+ .search-input-wrap {
+ width: 78%;
+ }
+ }
+}
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/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index e909e15f74c..e83fa9e3d52 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -6,7 +6,7 @@
.navbar-nav {
li {
.badge.todos-pending-count {
- background-color: #7f8fa4;
+ background-color: $gl-icon-color;
margin-top: -5px;
font-weight: normal;
}