summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2016-03-20 14:57:25 +0100
committerDouwe Maan <douwe@selenight.nl>2016-03-20 14:57:25 +0100
commit2eb19ea3ea36916bbea72a8ccab3e6d15f602ac9 (patch)
tree55c08bbb50e92ce76028f68a5267401a76bc4b02 /app
parent8b830b8c3b32774e8ccf562b8bc9dbce3ecf3073 (diff)
parent01fe50a72513a88f2168c8c0a649661b1382a42b (diff)
downloadgitlab-ce-2eb19ea3ea36916bbea72a8ccab3e6d15f602ac9.tar.gz
Merge branch 'master' into issue_12658
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee3
-rw-r--r--app/assets/javascripts/gl_dropdown.js.coffee6
-rw-r--r--app/assets/javascripts/issuable_form.js.coffee41
-rw-r--r--app/assets/javascripts/issue.js.coffee25
-rw-r--r--app/assets/javascripts/issues.js.coffee26
-rw-r--r--app/assets/javascripts/labels_select.js.coffee76
-rw-r--r--app/assets/javascripts/milestone_select.js.coffee51
-rw-r--r--app/assets/javascripts/notes.js.coffee5
-rw-r--r--app/assets/javascripts/project_new.js.coffee13
-rw-r--r--app/assets/javascripts/todos.js.coffee56
-rw-r--r--app/assets/javascripts/users_select.js.coffee35
-rw-r--r--app/assets/stylesheets/framework/blocks.scss6
-rw-r--r--app/assets/stylesheets/framework/buttons.scss25
-rw-r--r--app/assets/stylesheets/framework/calendar.scss8
-rw-r--r--app/assets/stylesheets/framework/callout.scss2
-rw-r--r--app/assets/stylesheets/framework/common.scss42
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss15
-rw-r--r--app/assets/stylesheets/framework/files.scss6
-rw-r--r--app/assets/stylesheets/framework/filters.scss17
-rw-r--r--app/assets/stylesheets/framework/forms.scss4
-rw-r--r--app/assets/stylesheets/framework/gitlab-theme.scss28
-rw-r--r--app/assets/stylesheets/framework/header.scss12
-rw-r--r--app/assets/stylesheets/framework/highlight.scss4
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss2
-rw-r--r--app/assets/stylesheets/framework/jquery.scss18
-rw-r--r--app/assets/stylesheets/framework/lists.scss11
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss4
-rw-r--r--app/assets/stylesheets/framework/mixins.scss8
-rw-r--r--app/assets/stylesheets/framework/mobile.scss6
-rw-r--r--app/assets/stylesheets/framework/nav.scss8
-rw-r--r--app/assets/stylesheets/framework/selects.scss4
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss14
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap.scss4
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap_variables.scss6
-rw-r--r--app/assets/stylesheets/framework/typography.scss8
-rw-r--r--app/assets/stylesheets/framework/variables.scss173
-rw-r--r--app/assets/stylesheets/framework/zen.scss2
-rw-r--r--app/assets/stylesheets/highlight/dark.scss18
-rw-r--r--app/assets/stylesheets/highlight/monokai.scss2
-rw-r--r--app/assets/stylesheets/highlight/solarized_dark.scss2
-rw-r--r--app/assets/stylesheets/highlight/solarized_light.scss2
-rw-r--r--app/assets/stylesheets/highlight/white.scss80
-rw-r--r--app/assets/stylesheets/pages/appearances.scss2
-rw-r--r--app/assets/stylesheets/pages/builds.scss2
-rw-r--r--app/assets/stylesheets/pages/commit.scss2
-rw-r--r--app/assets/stylesheets/pages/commits.scss8
-rw-r--r--app/assets/stylesheets/pages/dashboard.scss6
-rw-r--r--app/assets/stylesheets/pages/diff.scss52
-rw-r--r--app/assets/stylesheets/pages/editor.scss4
-rw-r--r--app/assets/stylesheets/pages/emojis.scss164
-rw-r--r--app/assets/stylesheets/pages/events.scss21
-rw-r--r--app/assets/stylesheets/pages/graph.scss4
-rw-r--r--app/assets/stylesheets/pages/import.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss155
-rw-r--r--app/assets/stylesheets/pages/issues.scss22
-rw-r--r--app/assets/stylesheets/pages/login.scss10
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss4
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--app/assets/stylesheets/pages/notes.scss31
-rw-r--r--app/assets/stylesheets/pages/profile.scss2
-rw-r--r--app/assets/stylesheets/pages/projects.scss33
-rw-r--r--app/assets/stylesheets/pages/runners.scss2
-rw-r--r--app/assets/stylesheets/pages/search.scss2
-rw-r--r--app/assets/stylesheets/pages/sherlock.scss4
-rw-r--r--app/assets/stylesheets/pages/status.scss2
-rw-r--r--app/assets/stylesheets/pages/todos.scss21
-rw-r--r--app/assets/stylesheets/pages/tree.scss4
-rw-r--r--app/assets/stylesheets/pages/ui_dev_kit.scss2
-rw-r--r--app/assets/stylesheets/pages/xterm.scss52
-rw-r--r--app/controllers/admin/abuse_reports_controller.rb2
-rw-r--r--app/controllers/admin/users_controller.rb4
-rw-r--r--app/controllers/dashboard/todos_controller.rb17
-rw-r--r--app/controllers/dashboard_controller.rb25
-rw-r--r--app/controllers/oauth/authorizations_controller.rb1
-rw-r--r--app/controllers/projects/badges_controller.rb13
-rw-r--r--app/controllers/projects/branches_controller.rb21
-rw-r--r--app/controllers/projects/issues_controller.rb9
-rw-r--r--app/controllers/projects/labels_controller.rb7
-rw-r--r--app/controllers/projects/merge_requests_controller.rb11
-rw-r--r--app/controllers/projects/milestones_controller.rb10
-rw-r--r--app/controllers/projects_controller.rb2
-rw-r--r--app/finders/issues_finder.rb6
-rw-r--r--app/helpers/application_helper.rb20
-rw-r--r--app/helpers/dropdowns_helper.rb2
-rw-r--r--app/helpers/events_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb17
-rw-r--r--app/helpers/issues_helper.rb4
-rw-r--r--app/helpers/labels_helper.rb34
-rw-r--r--app/helpers/milestones_helper.rb24
-rw-r--r--app/helpers/projects_helper.rb4
-rw-r--r--app/helpers/todos_helper.rb11
-rw-r--r--app/models/ability.rb17
-rw-r--r--app/models/abuse_report.rb4
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/models/concerns/milestoneish.rb20
-rw-r--r--app/models/event.rb6
-rw-r--r--app/models/issue.rb37
-rw-r--r--app/models/merge_request.rb19
-rw-r--r--app/models/milestone.rb4
-rw-r--r--app/models/project.rb5
-rw-r--r--app/models/project_wiki.rb8
-rw-r--r--app/models/repository.rb58
-rw-r--r--app/models/todo.rb32
-rw-r--r--app/models/wiki_page.rb2
-rw-r--r--app/services/commits/revert_service.rb7
-rw-r--r--app/services/delete_user_service.rb24
-rw-r--r--app/services/destroy_group_service.rb4
-rw-r--r--app/services/git_push_service.rb2
-rw-r--r--app/services/merge_requests/base_service.rb13
-rw-r--r--app/services/merge_requests/build_service.rb15
-rw-r--r--app/services/projects/autocomplete_service.rb6
-rw-r--r--app/services/projects/housekeeping_service.rb2
-rw-r--r--app/services/search/global_service.rb2
-rw-r--r--app/services/search/project_service.rb3
-rw-r--r--app/services/system_note_service.rb24
-rw-r--r--app/services/todo_service.rb65
-rw-r--r--app/views/admin/labels/_label.html.haml2
-rw-r--r--app/views/dashboard/todos/_todo.html.haml6
-rw-r--r--app/views/dashboard/todos/index.html.haml14
-rw-r--r--app/views/events/_event.html.haml2
-rw-r--r--app/views/layouts/header/_default.html.haml6
-rw-r--r--app/views/layouts/nav/_project.html.haml2
-rw-r--r--app/views/projects/_builds_settings.html.haml60
-rw-r--r--app/views/projects/diffs/_diffs.html.haml2
-rw-r--r--app/views/projects/diffs/_file.html.haml22
-rw-r--r--app/views/projects/diffs/_image.html.haml5
-rw-r--r--app/views/projects/edit.html.haml65
-rw-r--r--app/views/projects/issues/_issue.html.haml7
-rw-r--r--app/views/projects/issues/_merge_requests.html.haml2
-rw-r--r--app/views/projects/issues/_new_branch.html.haml5
-rw-r--r--app/views/projects/issues/_related_branches.html.haml15
-rw-r--r--app/views/projects/issues/show.html.haml15
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml6
-rw-r--r--app/views/projects/merge_requests/show/_mr_box.html.haml5
-rw-r--r--app/views/projects/merge_requests/show/_mr_title.html.haml13
-rw-r--r--app/views/projects/merge_requests/widget/open/_wip.html.haml10
-rw-r--r--app/views/projects/milestones/show.html.haml2
-rw-r--r--app/views/projects/notes/_note.html.haml10
-rw-r--r--app/views/projects/repositories/_download_archive.html.haml2
-rw-r--r--app/views/search/results/_issue.html.haml1
-rw-r--r--app/views/search/results/_wiki_blob.html.haml4
-rw-r--r--app/views/shared/_label_row.html.haml2
-rw-r--r--app/views/shared/groups/_group.html.haml13
-rw-r--r--app/views/shared/issuable/_filter.html.haml67
-rw-r--r--app/views/shared/issuable/_form.html.haml30
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml39
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml16
-rw-r--r--app/views/shared/issuable/_participants.html.haml16
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml48
-rw-r--r--app/views/shared/milestones/_issuable.html.haml2
-rw-r--r--app/views/shared/milestones/_labels_tab.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml4
-rw-r--r--app/views/shared/milestones/_summary.html.haml8
-rw-r--r--app/views/shared/milestones/_tabs.html.haml4
-rw-r--r--app/views/shared/milestones/_top.html.haml4
-rw-r--r--app/views/shared/projects/_project.html.haml34
-rw-r--r--app/views/shared/snippets/_snippet.html.haml4
-rw-r--r--app/workers/delete_user_worker.rb10
-rw-r--r--app/workers/gitlab_shell_one_shot_worker.rb10
-rw-r--r--app/workers/post_receive.rb46
160 files changed, 1669 insertions, 1093 deletions
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 1be86e3b820..f5e1ca9860d 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -14,7 +14,6 @@ class Dispatcher
path = page.split(':')
shortcut_handler = null
-
switch page
when 'projects:issues:index'
Issues.init()
@@ -25,6 +24,8 @@ class Dispatcher
new ZenMode()
when 'projects:milestones:show', 'groups:milestones:show', 'dashboard:milestones:show'
new Milestone()
+ when 'dashboard:todos:index'
+ new Todos()
when 'projects:milestones:new', 'projects:milestones:edit'
new ZenMode()
new DropzoneInput($('.milestone-form'))
diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee
index 4f038477755..c81e8bf760a 100644
--- a/app/assets/javascripts/gl_dropdown.js.coffee
+++ b/app/assets/javascripts/gl_dropdown.js.coffee
@@ -246,11 +246,15 @@ class GitLabDropdown
if oldValue
value = "#{oldValue},#{value}"
else
- @dropdown.find(ACTIVE_CLASS).removeClass ACTIVE_CLASS
+ @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
# Toggle active class for the tick mark
el.toggleClass "is-active"
+ # Toggle the dropdown label
+ if @options.toggleLabel
+ $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject)
+
if value?
if !field.length
# Create hidden input for form
diff --git a/app/assets/javascripts/issuable_form.js.coffee b/app/assets/javascripts/issuable_form.js.coffee
index 48c249943f2..6c1699c178c 100644
--- a/app/assets/javascripts/issuable_form.js.coffee
+++ b/app/assets/javascripts/issuable_form.js.coffee
@@ -1,4 +1,5 @@
class @IssuableForm
+ wipRegex: /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i
constructor: (@form) ->
GitLab.GfmAutoComplete.setup()
new UsersSelect()
@@ -14,6 +15,8 @@ class @IssuableForm
@form.on "submit", @resetAutosave
@form.on "click", ".btn-cancel", @resetAutosave
+ @initWip()
+
initAutosave: ->
new Autosave @titleField, [
document.location.pathname,
@@ -30,3 +33,41 @@ class @IssuableForm
resetAutosave: =>
@titleField.data("autosave").reset()
@descriptionField.data("autosave").reset()
+
+ initWip: ->
+ @$wipExplanation = @form.find(".js-wip-explanation")
+ @$noWipExplanation = @form.find(".js-no-wip-explanation")
+ return unless @$wipExplanation.length and @$noWipExplanation.length
+
+ @form.on "click", ".js-toggle-wip", @toggleWip
+
+ @titleField.on "keyup blur", @renderWipExplanation
+
+ @renderWipExplanation()
+
+ workInProgress: ->
+ @wipRegex.test @titleField.val()
+
+ renderWipExplanation: =>
+ if @workInProgress()
+ @$wipExplanation.show()
+ @$noWipExplanation.hide()
+ else
+ @$wipExplanation.hide()
+ @$noWipExplanation.show()
+
+ toggleWip: (event) =>
+ event.preventDefault()
+
+ if @workInProgress()
+ @removeWip()
+ else
+ @addWip()
+
+ @renderWipExplanation()
+
+ removeWip: ->
+ @titleField.val @titleField.val().replace(@wipRegex, "")
+
+ addWip: ->
+ @titleField.val "WIP: #{@titleField.val()}"
diff --git a/app/assets/javascripts/issue.js.coffee b/app/assets/javascripts/issue.js.coffee
index d663e34871c..f50df1f5ea3 100644
--- a/app/assets/javascripts/issue.js.coffee
+++ b/app/assets/javascripts/issue.js.coffee
@@ -7,6 +7,7 @@ class @Issue
# Prevent duplicate event bindings
@disableTaskList()
@fixAffixScroll()
+ @initParticipants()
if $('a.btn-close').length
@initTaskList()
@initIssueBtnEventListeners()
@@ -84,3 +85,27 @@ class @Issue
type: 'PATCH'
url: $('form.js-issuable-update').attr('action')
data: patchData
+
+ initParticipants: ->
+ _this = @
+ $(document).on "click", ".js-participants-more", @toggleHiddenParticipants
+
+ $(".js-participants-author").each (i) ->
+ if i >= _this.PARTICIPANTS_ROW_COUNT
+ $(@)
+ .addClass "js-participants-hidden"
+ .hide()
+
+ toggleHiddenParticipants: (e) ->
+ e.preventDefault()
+
+ currentText = $(this).text().trim()
+ lessText = $(this).data("less-text")
+ originalText = $(this).data("original-text")
+
+ if currentText is originalText
+ $(this).text(lessText)
+ else
+ $(this).text(originalText)
+
+ $(".js-participants-hidden").toggle()
diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee
index a0acf3028bf..1127b289264 100644
--- a/app/assets/javascripts/issues.js.coffee
+++ b/app/assets/javascripts/issues.js.coffee
@@ -41,24 +41,28 @@
@timer = null
$("#issue_search").keyup ->
clearTimeout(@timer)
- @timer = setTimeout(Issues.filterResults, 500)
+ @timer = setTimeout( ->
+ Issues.filterResults $("#issue_search_form")
+ , 500)
- filterResults: =>
- form = $("#issue_search_form")
- search = $("#issue_search").val()
- $('.issues-holder').css("opacity", '0.5')
- issues_url = form.attr('action') + '?' + form.serialize()
+ filterResults: (form) =>
+ $('.issues-holder, .merge-requests-holder').css("opacity", '0.5')
+ formAction = form.attr('action')
+ formData = form.serialize()
+ issuesUrl = formAction
+ issuesUrl += ("#{if formAction.indexOf("?") < 0 then '?' else '&'}")
+ issuesUrl += formData
$.ajax
type: "GET"
- url: form.attr('action')
- data: form.serialize()
+ url: formAction
+ data: formData
complete: ->
- $('.issues-holder').css("opacity", '1.0')
+ $('.issues-holder, .merge-requests-holder').css("opacity", '1.0')
success: (data) ->
- $('.issues-holder').html(data.html)
+ $('.issues-holder, .merge-requests-holder').html(data.html)
# Change url so if user reload a page - search results are saved
- history.replaceState {page: issues_url}, document.title, issues_url
+ history.replaceState {page: issuesUrl}, document.title, issuesUrl
Issues.reload()
dataType: "json"
diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee
index 5ade2cb66cb..4a0c18a99a6 100644
--- a/app/assets/javascripts/labels_select.js.coffee
+++ b/app/assets/javascripts/labels_select.js.coffee
@@ -1,30 +1,32 @@
class @LabelsSelect
constructor: ->
$('.js-label-select').each (i, dropdown) ->
- projectId = $(dropdown).data('project-id')
- labelUrl = $(dropdown).data("labels")
- selectedLabel = $(dropdown).data('selected')
+ $dropdown = $(dropdown)
+ projectId = $dropdown.data('project-id')
+ labelUrl = $dropdown.data('labels')
+ selectedLabel = $dropdown.data('selected')
if selectedLabel
- selectedLabel = selectedLabel.split(",")
+ selectedLabel = selectedLabel.split(',')
newLabelField = $('#new_label_name')
newColorField = $('#new_label_color')
- showNo = $(dropdown).data('show-no')
- showAny = $(dropdown).data('show-any')
+ showNo = $dropdown.data('show-no')
+ showAny = $dropdown.data('show-any')
+ defaultLabel = $dropdown.data('default-label')
if newLabelField.length
- $('.suggest-colors-dropdown a').on "click", (e) ->
+ $('.suggest-colors-dropdown a').on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
- newColorField.val $(this).data("color")
+ newColorField.val $(this).data('color')
$('.js-dropdown-label-color-preview')
- .css 'background-color', $(this).data("color")
+ .css 'background-color', $(this).data('color')
.addClass 'is-active'
- $('.js-new-label-btn').on "click", (e) ->
+ $('.js-new-label-btn').on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
- if newLabelField.val() isnt "" && newColorField.val() isnt ""
+ if newLabelField.val() isnt '' and newColorField.val() isnt ''
$('.js-new-label-btn').disable()
# Create new label with API
@@ -33,46 +35,38 @@ class @LabelsSelect
color: newColorField.val()
}, (label) ->
$('.js-new-label-btn').enable()
- $('.dropdown-menu-back', $(dropdown).parent()).trigger "click"
+ $('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
- $(dropdown).glDropdown(
+ $dropdown.glDropdown(
data: (term, callback) ->
- # We have to fetch the JS version of the labels list because there is no
- # public facing JSON url for labels
$.ajax(
url: labelUrl
).done (data) ->
- html = $(data)
- data = []
- html.find('.label-row a').each ->
- data.push(
- title: $(@).text().trim()
- )
-
if showNo
data.unshift(
- id: "0"
- title: 'No label'
+ id: 0
+ title: 'No Label'
)
if showAny
data.unshift(
- title: 'Any label'
+ isAny: true
+ title: 'Any Label'
)
if data.length > 2
- data.splice 2, 0, "divider"
+ data.splice 2, 0, 'divider'
callback data
renderRow: (label) ->
if $.isArray(selectedLabel)
- selected = ""
+ selected = ''
$.each selectedLabel, (i, selectedLbl) ->
selectedLbl = selectedLbl.trim()
- if selected is "" && label.title is selectedLbl
- selected = "is-active"
+ if selected is '' and label.title is selectedLbl
+ selected = 'is-active'
else
- selected = if label.title is selectedLabel then "is-active" else ""
+ selected = if label.title is selectedLabel then 'is-active' else ''
"<li>
<a href='#' class='#{selected}'>
@@ -83,10 +77,24 @@ class @LabelsSelect
search:
fields: ['title']
selectable: true
- fieldName: $(dropdown).data('field-name')
+ toggleLabel: (selected) ->
+ if selected and selected.title isnt 'Any Label'
+ selected.title
+ else
+ defaultLabel
+ fieldName: $dropdown.data('field-name')
id: (label) ->
- label.title
+ if label.isAny?
+ ''
+ else
+ label.title
clicked: ->
- if $(dropdown).hasClass "js-filter-submit"
- $(dropdown).parents('form').submit()
+ page = $('body').data 'page'
+ isIssueIndex = page is 'projects:issues:index'
+ isMRIndex = page is page is 'projects:merge_requests:index'
+
+ if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
+ Issues.filterResults $dropdown.closest('form')
+ else if $dropdown.hasClass 'js-filter-submit'
+ $dropdown.closest('form').submit()
)
diff --git a/app/assets/javascripts/milestone_select.js.coffee b/app/assets/javascripts/milestone_select.js.coffee
index 5e884454a65..e17a1adb648 100644
--- a/app/assets/javascripts/milestone_select.js.coffee
+++ b/app/assets/javascripts/milestone_select.js.coffee
@@ -1,60 +1,65 @@
class @MilestoneSelect
constructor: ->
$('.js-milestone-select').each (i, dropdown) ->
- projectId = $(dropdown).data('project-id')
- milestonesUrl = $(dropdown).data('milestones')
- selectedMilestone = $(dropdown).data('selected')
- showNo = $(dropdown).data('show-no')
- showAny = $(dropdown).data('show-any')
- useId = $(dropdown).data('use-id')
+ $dropdown = $(dropdown)
+ projectId = $dropdown.data('project-id')
+ milestonesUrl = $dropdown.data('milestones')
+ selectedMilestone = $dropdown.data('selected')
+ showNo = $dropdown.data('show-no')
+ showAny = $dropdown.data('show-any')
+ useId = $dropdown.data('use-id')
+ defaultLabel = $dropdown.data('default-label')
- $(dropdown).glDropdown(
+ $dropdown.glDropdown(
data: (term, callback) ->
$.ajax(
url: milestonesUrl
).done (data) ->
- html = $(data)
- data = []
- html.find('.milestone strong a').each ->
- link = $(@).attr("href").split("/")
- data.push(
- id: link[link.length - 1]
- title: $(@).text().trim()
- )
-
if showNo
data.unshift(
- id: "0"
+ id: '0'
title: 'No Milestone'
)
if showAny
data.unshift(
+ isAny: true
title: 'Any Milestone'
)
if data.length > 2
- data.splice 2, 0, "divider"
+ data.splice 2, 0, 'divider'
callback(data)
filterable: true
search:
fields: ['title']
selectable: true
- fieldName: $(dropdown).data('field-name')
+ toggleLabel: (selected) ->
+ if selected && 'id' of selected
+ selected.title
+ else
+ defaultLabel
+ fieldName: $dropdown.data('field-name')
text: (milestone) ->
milestone.title
id: (milestone) ->
if !useId
- if milestone.title isnt "Any milestone"
+ if !milestone.isAny?
milestone.title
else
- ""
+ ''
else
milestone.id
isSelected: (milestone) ->
milestone.title is selectedMilestone
clicked: ->
- if $(dropdown).hasClass "js-filter-submit"
- $(dropdown).parents('form').submit()
+ page = $('body').data 'page'
+ isIssueIndex = page is 'projects:issues:index'
+ isMRIndex = page is page is 'projects:merge_requests:index'
+
+ if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
+ Issues.filterResults $dropdown.closest('form')
+ else if $dropdown.hasClass 'js-filter-submit'
+ $dropdown.closest('form').submit()
)
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 75d7f52bbb6..82532216589 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -343,6 +343,7 @@ class @Notes
updateNote: (_xhr, note, _status) =>
# Convert returned HTML to a jQuery object so we can modify it further
$html = $(note.html)
+ $('.js-timeago', $html).timeago()
$html.syntaxHighlight()
$html.find('.js-task-list-container').taskList('enable')
@@ -626,10 +627,10 @@ class @Notes
if closebtn.text() isnt closetext
closebtn.text(closetext)
- if reopenbtn.is(':not(.btn-comment-and-reopen)')
+ if reopenbtn.is('.btn-comment-and-reopen')
reopenbtn.removeClass('btn-comment-and-reopen')
- if closebtn.is(':not(.btn-comment-and-close)')
+ if closebtn.is('.btn-comment-and-close')
closebtn.removeClass('btn-comment-and-close')
if discardbtn.is(':visible')
diff --git a/app/assets/javascripts/project_new.js.coffee b/app/assets/javascripts/project_new.js.coffee
index fecdb9fc2e7..63dee4ed5d7 100644
--- a/app/assets/javascripts/project_new.js.coffee
+++ b/app/assets/javascripts/project_new.js.coffee
@@ -3,3 +3,16 @@ class @ProjectNew
$('.project-edit-container').on 'ajax:before', =>
$('.project-edit-container').hide()
$('.save-project-loader').show()
+ @toggleSettings()
+ @toggleSettingsOnclick()
+
+
+ toggleSettings: ->
+ checked = $("#project_builds_enabled").prop("checked")
+ if checked
+ $('.builds-feature').show()
+ else
+ $('.builds-feature').hide()
+
+ toggleSettingsOnclick: ->
+ $("#project_builds_enabled").on 'click', @toggleSettings
diff --git a/app/assets/javascripts/todos.js.coffee b/app/assets/javascripts/todos.js.coffee
new file mode 100644
index 00000000000..b6b4bd90e6a
--- /dev/null
+++ b/app/assets/javascripts/todos.js.coffee
@@ -0,0 +1,56 @@
+class @Todos
+ constructor: (@name) ->
+ @clearListeners()
+ @initBtnListeners()
+
+ clearListeners: ->
+ $('.done-todo').off('click')
+ $('.js-todos-mark-all').off('click')
+
+ initBtnListeners: ->
+ $('.done-todo').on('click', @doneClicked)
+ $('.js-todos-mark-all').on('click', @allDoneClicked)
+
+ doneClicked: (e) =>
+ e.preventDefault()
+ e.stopImmediatePropagation()
+
+ $this = $(e.currentTarget)
+ $this.disable()
+
+ $.ajax
+ type: 'POST'
+ url: $this.attr('href')
+ dataType: 'json'
+ data: '_method': 'delete'
+ success: (data) =>
+ @clearDone $this.closest('li')
+ @updateBadges data
+
+ allDoneClicked: (e) =>
+ e.preventDefault()
+ e.stopImmediatePropagation()
+
+ $this = $(e.currentTarget)
+ $this.disable()
+
+ $.ajax
+ type: 'POST'
+ url: $this.attr('href')
+ dataType: 'json'
+ data: '_method': 'delete'
+ success: (data) =>
+ $this.remove()
+ $('.js-todos-list').remove()
+ @updateBadges data
+
+ clearDone: ($row) ->
+ $ul = $row.closest('ul')
+ $row.remove()
+
+ if not $ul.find('li').length
+ $ul.parents('.panel').remove()
+
+ updateBadges: (data) ->
+ $('.todos-pending .badge, .todos-pending-count').text data.count
+ $('.todos-done .badge').text data.done_count
diff --git a/app/assets/javascripts/users_select.js.coffee b/app/assets/javascripts/users_select.js.coffee
index 987c6f4b8d2..3d6452d2f46 100644
--- a/app/assets/javascripts/users_select.js.coffee
+++ b/app/assets/javascripts/users_select.js.coffee
@@ -4,14 +4,16 @@ class @UsersSelect
@userPath = "/autocomplete/users/:id.json"
$('.js-user-search').each (i, dropdown) =>
- @projectId = $(dropdown).data('project-id')
- @showCurrentUser = $(dropdown).data('current-user')
- showNullUser = $(dropdown).data('null-user')
- showAnyUser = $(dropdown).data('any-user')
- firstUser = $(dropdown).data('first-user')
- selectedId = $(dropdown).data('selected')
-
- $(dropdown).glDropdown(
+ $dropdown = $(dropdown)
+ @projectId = $dropdown.data('project-id')
+ @showCurrentUser = $dropdown.data('current-user')
+ showNullUser = $dropdown.data('null-user')
+ showAnyUser = $dropdown.data('any-user')
+ firstUser = $dropdown.data('first-user')
+ selectedId = $dropdown.data('selected')
+ defaultLabel = $dropdown.data('default-label')
+
+ $dropdown.glDropdown(
data: (term, callback) =>
@users term, (users) =>
if term.length is 0
@@ -52,10 +54,21 @@ class @UsersSelect
search:
fields: ['name', 'username']
selectable: true
- fieldName: $(dropdown).data('field-name')
+ fieldName: $dropdown.data('field-name')
+ toggleLabel: (selected) ->
+ if selected && 'id' of selected
+ selected.name
+ else
+ defaultLabel
clicked: ->
- if $(dropdown).hasClass "js-filter-submit"
- $(dropdown).parents('form').submit()
+ page = $('body').data 'page'
+ isIssueIndex = page is 'projects:issues:index'
+ isMRIndex = page is page is 'projects:merge_requests:index'
+
+ if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
+ Issues.filterResults $dropdown.closest('form')
+ else if $dropdown.hasClass 'js-filter-submit'
+ $dropdown.closest('form').submit()
renderRow: (user) ->
username = if user.username then "@#{user.username}" else ""
avatar = if user.avatar_url then user.avatar_url else false
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 31084872367..2fac6abbac9 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -23,15 +23,11 @@
margin-bottom: -$gl-padding;
background-color: $background-color;
padding: $gl-padding;
- margin-bottom: 0px;
+ margin-bottom: 0;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
color: $gl-gray;
- a {
- color: $md-link-color;
- }
-
&.oneline-block {
line-height: 42px;
}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 8d475137b03..657c5f033c7 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -37,23 +37,23 @@
}
@mixin btn-green {
- @include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #FFFFFF);
+ @include btn-color($green-light, $border-green-light, $green-normal, $border-green-normal, $green-dark, $border-green-dark, #fff);
}
@mixin btn-blue {
- @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #FFFFFF);
+ @include btn-color($blue-light, $border-blue-light, $blue-normal, $border-blue-normal, $blue-dark, $border-blue-dark, #fff);
}
@mixin btn-blue-medium {
- @include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #FFFFFF);
+ @include btn-color($blue-medium-light, $border-blue-light, $blue-medium, $border-blue-normal, $blue-medium-dark, $border-blue-dark, #fff);
}
@mixin btn-orange {
- @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #FFFFFF);
+ @include btn-color($orange-light, $border-orange-light, $orange-normal, $border-orange-normal, $orange-dark, $border-orange-dark, #fff);
}
@mixin btn-red {
- @include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #FFFFFF);
+ @include btn-color($red-light, $border-red-light, $red-normal, $border-red-normal, $red-dark, $border-red-dark, #fff);
}
@mixin btn-gray {
@@ -127,7 +127,7 @@
margin-right: 7px;
float: left;
&:last-child {
- margin-right: 0px;
+ margin-right: 0;
}
&.btn-xs {
margin-right: 3px;
@@ -139,7 +139,6 @@
.caret {
margin-left: 5px;
- color: $gray-darkest;
}
}
@@ -170,7 +169,7 @@
margin-right: 7px;
float: left;
&:last-child {
- margin-right: 0px;
+ margin-right: 0;
}
}
}
@@ -209,3 +208,13 @@
background-color: #e4e7ed !important;
}
}
+
+.btn-loading {
+ &:not(.disabled) .fa {
+ display: none;
+ }
+
+ .fa {
+ margin-right: 5px;
+ }
+}
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 580012abd77..e3192823a1a 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -33,19 +33,19 @@
}
.q2 {
- fill: #ACD5F2 !important;
+ fill: #acd5f2 !important;
}
.q3 {
- fill: #7FA8D1 !important;
+ fill: #7fa8d1 !important;
}
.q4 {
- fill: #49729B !important;
+ fill: #49729b !important;
}
.q5 {
- fill: #254E77 !important;
+ fill: #254e77 !important;
}
.domain-background {
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index 20a9bfb9816..da7bab74a32 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -39,6 +39,6 @@
}
.bs-callout-success {
background-color: #dff0d8;
- border-color: #5cA64d;
+ border-color: #5ca64d;
color: #3c763d;
}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index ff551f151f1..bc03c2180be 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -1,6 +1,6 @@
/** COLORS **/
.cgray { color: $gl-gray; }
-.clgray { color: #BBB }
+.clgray { color: #bbb }
.cred { color: $gl-text-red; }
.cgreen { color: $gl-text-green; }
.cdark { color: #444 }
@@ -8,20 +8,20 @@
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
-.prepend-top-10 { margin-top:10px }
+.prepend-top-10 { margin-top: 10px }
.prepend-top-default { margin-top: $gl-padding !important; }
-.prepend-top-20 { margin-top:20px }
-.prepend-left-10 { margin-left:10px }
+.prepend-top-20 { margin-top: 20px }
+.prepend-left-10 { margin-left: 10px }
.prepend-left-default { margin-left: $gl-padding; }
-.prepend-left-20 { margin-left:20px }
+.prepend-left-20 { margin-left: 20px }
.append-right-5 { margin-right: 5px }
-.append-right-10 { margin-right:10px }
+.append-right-10 { margin-right: 10px }
.append-right-default { margin-right: $gl-padding; }
-.append-right-20 { margin-right:20px }
-.append-bottom-0 { margin-bottom:0 }
-.append-bottom-10 { margin-bottom:10px }
-.append-bottom-15 { margin-bottom:15px }
-.append-bottom-20 { margin-bottom:20px }
+.append-right-20 { margin-right: 20px }
+.append-bottom-0 { margin-bottom: 0 }
+.append-bottom-10 { margin-bottom: 10px }
+.append-bottom-15 { margin-bottom: 15px }
+.append-bottom-20 { margin-bottom: 20px }
.append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block }
.center { text-align: center }
@@ -51,7 +51,7 @@ pre {
}
&.well-pre {
- border: 1px solid #EEE;
+ border: 1px solid #eee;
background: #f9f9f9;
border-radius: 0;
color: #555;
@@ -103,7 +103,7 @@ span.update-author {
}
.user-mention {
- color: #2FA0BB;
+ color: #2fa0bb;
font-weight: bold;
}
@@ -134,10 +134,10 @@ p.time {
// Fix issue with notes & lists creating a bunch of bottom borders.
li.note {
- img { max-width:100% }
+ img { max-width: 100% }
.note-title {
li {
- border-bottom:none !important;
+ border-bottom: none !important;
}
}
}
@@ -187,9 +187,9 @@ li.note {
.error-message {
padding: 10px;
- background: #C67;
+ background: #c67;
margin: 0;
- color: #FFF;
+ color: #fff;
a {
color: #fff;
@@ -200,7 +200,7 @@ li.note {
.browser-alert {
padding: 10px;
text-align: center;
- background: #C67;
+ background: #c67;
color: #fff;
font-weight: bold;
a {
@@ -271,7 +271,7 @@ img.emoji {
table {
td.permission-x {
- background: #D9EDF7 !important;
+ background: #d9edf7 !important;
text-align: center;
}
}
@@ -280,7 +280,7 @@ table {
float: left;
text-align: center;
font-size: 32px;
- color: #AAA;
+ color: #aaa;
width: 60px;
}
@@ -347,7 +347,7 @@ table {
.profiler-button,
.profiler-controls {
- border-color: #EEE !important;
+ border-color: #eee !important;
}
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 5b647fc6176..a48b6c17fa0 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -4,11 +4,17 @@
height: 0;
margin-left: 2px;
vertical-align: middle;
- border-top: $caret-width-base dashed $dropdown-caret-color;
+ border-top: $caret-width-base dashed;
border-right: $caret-width-base solid transparent;
border-left: $caret-width-base solid transparent;
}
+.btn-group {
+ .caret {
+ margin-left: 0;
+ }
+}
+
.dropdown {
position: relative;
}
@@ -161,9 +167,8 @@
.dropdown-menu-user-full-name {
display: block;
- margin-bottom: 2px;
font-weight: 600;
- line-height: 1;
+ line-height: 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
@@ -171,7 +176,7 @@
.dropdown-menu-user-username {
display: block;
- line-height: 1;
+ line-height: 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
@@ -261,7 +266,7 @@
position: absolute;
top: 10px;
right: 10px;
- color: #C7C7C7;
+ color: #c7c7c7;
font-size: 12px;
pointer-events: none;
}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index b034a4882c1..646e2610831 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -30,7 +30,7 @@
right: 15px;
.btn {
- padding: 0px 10px;
+ padding: 0 10px;
font-size: 13px;
line-height: 28px;
}
@@ -84,7 +84,7 @@
&.blob-no-preview {
background: #eee;
- text-shadow: 0 1px 2px #FFF;
+ text-shadow: 0 1px 2px #fff;
padding: 100px 0;
}
@@ -124,7 +124,7 @@
}
td.line-numbers {
float: none;
- border-left: 1px solid #DDD;
+ border-left: 1px solid #ddd;
}
td.lines {
padding: 0;
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index c431e2b0df3..40a508c1ebc 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -3,22 +3,11 @@
vertical-align: top;
}
-@media (min-width: 800px) {
+@media (min-width: $screen-sm-min) {
.issues-filters,
.issues_bulk_update {
- select, .select2-container {
- width: 120px !important;
- display: inline-block;
- }
- }
-}
-
-@media (min-width: 1200px) {
- .issues-filters,
- .issues_bulk_update {
- select, .select2-container {
- width: 150px !important;
- display: inline-block;
+ .dropdown-menu-toggle {
+ width: 132px;
}
}
}
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 6c08005812e..4cb4129b71b 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -41,8 +41,8 @@ input[type='search'].search-input {
}
input[type='text'].danger {
- background: #F2DEDE!important;
- border-color: #D66;
+ background: #f2dede!important;
+ border-color: #d66;
text-shadow: 0 1px 1px #fff
}
diff --git a/app/assets/stylesheets/framework/gitlab-theme.scss b/app/assets/stylesheets/framework/gitlab-theme.scss
index 12cef6f8ea1..2a4cf4fc335 100644
--- a/app/assets/stylesheets/framework/gitlab-theme.scss
+++ b/app/assets/stylesheets/framework/gitlab-theme.scss
@@ -23,13 +23,13 @@
&:hover {
background-color: $color-darker;
a {
- color: #FFF;
+ color: #fff;
}
}
}
.collapse-nav a {
- color: #FFF;
+ color: #fff;
background: $color;
}
@@ -42,7 +42,7 @@
&:hover {
background-color: $color-dark;
- color: #FFF;
+ color: #fff;
text-decoration: none;
}
}
@@ -71,7 +71,7 @@
}
&.active a {
- color: #FFF;
+ color: #fff;
background: $color-dark;
&.no-highlight {
@@ -79,42 +79,42 @@
}
i {
- color: #FFF
+ color: #fff
}
}
}
}
}
-$theme-blue: #2980B9;
+$theme-blue: #2980b9;
$theme-charcoal: #333c47;
-$theme-graphite: #888888;
+$theme-graphite: #888;
$theme-gray: #373737;
$theme-green: #019875;
-$theme-violet: #554488;
+$theme-violet: #548;
body {
&.ui_blue {
- @include gitlab-theme(#BECDE9, $theme-blue, #1970A9, #096099);
+ @include gitlab-theme(#becde9, $theme-blue, #1970a9, #096099);
}
&.ui_charcoal {
- @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272D);
+ @include gitlab-theme(#c5d0de, $theme-charcoal, #2b333d, #24272d);
}
&.ui_graphite {
- @include gitlab-theme(#CCCCCC, $theme-graphite, #777777, #666666);
+ @include gitlab-theme(#ccc, $theme-graphite, #777, #666);
}
&.ui_gray {
- @include gitlab-theme(#979797, $theme-gray, #272727, #222222);
+ @include gitlab-theme(#979797, $theme-gray, #272727, #222);
}
&.ui_green {
- @include gitlab-theme(#AADDCC, $theme-green, #018865, #017855);
+ @include gitlab-theme(#adc, $theme-green, #018865, #017855);
}
&.ui_violet {
- @include gitlab-theme(#9988CC, $theme-violet, #443366, #332255);
+ @include gitlab-theme(#98c, $theme-violet, #436, #325);
}
} \ No newline at end of file
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 4c4033e3ae7..71a7ecab8ef 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -7,8 +7,8 @@ header {
&.navbar-empty {
height: 58px;
- background: #FFF;
- border-bottom: 1px solid #EEE;
+ background: #fff;
+ border-bottom: 1px solid #eee;
.center-logo {
margin: 11px 0;
@@ -28,7 +28,7 @@ header {
min-height: $header-height;
background-color: #fff;
border: none;
- border-bottom: 1px solid #EEE;
+ border-bottom: 1px solid #eee;
.container-fluid {
width: 100% !important;
@@ -47,7 +47,7 @@ header {
text-align: center;
&:hover, &:focus, &:active {
- background-color: #FFF;
+ background-color: #fff;
}
}
@@ -59,7 +59,7 @@ header {
right: 2px;
&:hover {
- background-color: #EEE;
+ background-color: #eee;
}
&.active {
color: #7f8fa4;
@@ -162,7 +162,7 @@ header {
font-size: 18px;
.navbar-nav {
- margin: 0px;
+ margin: 0;
float: none !important;
.visible-xs, .visable-sm {
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 12e2f00fe89..7cf4d4fba42 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -1,8 +1,8 @@
.file-content.code {
border: none;
box-shadow: none;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
table-layout: fixed;
pre {
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index 77a00586b26..7f7b7c806e7 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -20,7 +20,7 @@
display: block;
float: left;
margin-right: 10px;
- color: #FFF;
+ color: #fff;
font-size: $gl-font-size;
line-height: 25px;
diff --git a/app/assets/stylesheets/framework/jquery.scss b/app/assets/stylesheets/framework/jquery.scss
index 0cdcd923b3c..525ed81b059 100644
--- a/app/assets/stylesheets/framework/jquery.scss
+++ b/app/assets/stylesheets/framework/jquery.scss
@@ -3,13 +3,13 @@
font-size: $font-size-base;
&.ui-datepicker-inline {
- border: 1px solid #DDD;
+ border: 1px solid #ddd;
padding: 10px;
width: 270px;
.ui-datepicker-header {
- background: #FFF;
- border-color: #DDD;
+ background: #fff;
+ border-color: #ddd;
}
.ui-datepicker-calendar td a {
@@ -19,7 +19,7 @@
}
&.ui-autocomplete {
- border-color: #DDD;
+ border-color: #ddd;
padding: 0;
margin-top: 2px;
z-index: 1001;
@@ -30,20 +30,20 @@
}
.ui-state-default {
- border: 1px solid #FFF;
- background: #FFF;
+ border: 1px solid #fff;
+ background: #fff;
color: #777;
}
.ui-state-highlight {
- border: 1px solid #EEE;
- background: #EEE;
+ border: 1px solid #eee;
+ background: #eee;
}
.ui-state-active {
border: 1px solid $gl-primary;
background: $gl-primary;
- color: #FFF;
+ color: #fff;
}
.ui-state-hover,
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index bfec0911b3c..b17c8bcbb1e 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -111,14 +111,17 @@ ul.content-list {
> li {
border-color: $table-border-color;
- color: $list-text-color;
font-size: $list-font-size;
+ color: $list-text-color;
.title {
- color: $list-title-color;
font-weight: 600;
}
+ a {
+ color: $gl-dark-link-color;
+ }
+
.description {
p {
@include str-truncated;
@@ -141,6 +144,10 @@ ul.content-list {
}
}
+.panel > .content-list > li {
+ padding: $gl-padding-top $gl-padding;
+}
+
ul.controls {
padding-top: 1px;
float: right;
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 1d8611b04dc..8328aac4e7a 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -71,7 +71,7 @@
}
.md-preview-holder {
- background: #FFF;
+ background: #fff;
border: 1px solid #ddd;
min-height: 169px;
padding: 5px;
@@ -80,7 +80,7 @@
.markdown-area {
@include border-radius(0);
- background: #FFF;
+ background: #fff;
border: 1px solid #ddd;
min-height: 140px;
max-height: 500px;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 1d5000fe388..377bfa174bd 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -67,17 +67,17 @@
* Base mixin for lists in GitLab
*/
@mixin basic-list {
- margin: 5px 0px;
- padding: 0px;
+ margin: 5px 0;
+ padding: 0;
list-style: none;
> li {
@include clearfix;
padding: 10px 0;
- border-bottom: 1px solid #EEE;
+ border-bottom: 1px solid #eee;
display: block;
- margin: 0px;
+ margin: 0;
&:last-child {
border-bottom: none;
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index d088228fe4c..bf874b9b822 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -128,12 +128,12 @@
.show-aside {
display: none;
position: fixed;
- right: 0px;
+ right: 0;
top: 30%;
padding: 5px 15px;
- background: #EEE;
+ background: #eee;
font-size: 20px;
color: #777;
z-index: 100;
- @include box-shadow(0 1px 2px #DDD);
+ @include box-shadow(0 1px 2px #ddd);
}
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index b2fbc95e043..5f4ce87b085 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -26,7 +26,7 @@
}
&.active a {
- color: #000000;
+ color: #000;
border-bottom: 2px solid #4688f1;
}
@@ -41,7 +41,7 @@
.top-area {
@include clearfix;
- border-bottom: 1px solid #EEE;
+ border-bottom: 1px solid #eee;
.nav-text {
padding-top: 16px;
@@ -59,7 +59,7 @@
.nav-links {
display: inline-block;
width: 50%;
- margin-bottom: 0px;
+ margin-bottom: 0;
border-bottom: none;
/* Small devices (phones, tablets, 768px and lower) */
@@ -74,7 +74,7 @@
float: right;
text-align: right;
padding: 11px 0;
- margin-bottom: 0px;
+ margin-bottom: 0;
> .dropdown {
margin-right: $gl-padding-top;
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 7bf04e4ad74..b3371229d5a 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -151,7 +151,7 @@
padding: 2px 25px 2px 5px;
background: #fff image-url('select2.png');
background-repeat: no-repeat;
- background-position: right 0px bottom 6px;
+ background-position: right 0 bottom 6px;
border: 1px solid $input-border;
@include border-radius($border-radius-default);
@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
@@ -229,7 +229,7 @@
.namespace-result {
.namespace-kind {
- color: #AAA;
+ color: #aaa;
font-weight: normal;
}
.namespace-path {
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 26df9acd2ae..be05db58c40 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -16,7 +16,7 @@
.gitlab-text-container-link {
z-index: 1;
position: absolute;
- left: 0px;
+ left: 0;
}
#logo {
@@ -47,7 +47,7 @@
width: 100%;
.container-fluid {
- background: #FFF;
+ background: #fff;
padding: 0 $gl-padding;
&.container-blank {
@@ -103,7 +103,7 @@
}
&:hover {
- background-color: #EEE;
+ background-color: #eee;
}
}
@@ -143,7 +143,7 @@
overflow: hidden;
&.navbar-collapse {
- padding: 0px !important;
+ padding: 0 !important;
}
li {
@@ -182,7 +182,7 @@
.count {
float: right;
background: #eee;
- padding: 0px 8px;
+ padding: 0 8px;
@include border-radius(6px);
}
@@ -194,8 +194,8 @@
}
.sidebar-subnav {
- margin-left: 0px;
- padding-left: 0px;
+ margin-left: 0;
+ padding-left: 0;
li {
list-style: none;
diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss
index ddf76704a53..dd42db1840f 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap.scss
@@ -95,7 +95,7 @@
}
&.label-inverse {
- background-color: #333333;
+ background-color: #333;
}
}
@@ -138,7 +138,7 @@
}
.btn-clipboard {
- min-width: 0px;
+ min-width: 0;
}
}
diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index b1b8295411b..f63ac033234 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -57,7 +57,7 @@ $component-active-bg: $brand-info;
$input-color: $text-color;
$input-border: #e7e9ed;
-$input-border-focus: #7F8FA4;
+$input-border-focus: #7f8fa4;
$legend-color: $text-color;
@@ -125,8 +125,8 @@ $panel-inner-border: $border-color;
//
//##
-$well-bg: #F9F9F9;
-$well-border: #EEE;
+$well-bg: #f9f9f9;
+$well-border: #eee;
//== Code
//
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 9381cb3281c..949295a1d0c 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -27,13 +27,13 @@
line-height: 10px;
color: #555;
vertical-align: middle;
- background-color: #FCFCFC;
+ background-color: #fcfcfc;
border-width: 1px;
border-style: solid;
- border-color: #CCC #CCC #BBB;
+ border-color: #ccc #ccc #bbb;
border-image: none;
border-radius: 3px;
- box-shadow: 0px -1px 0px #BBB inset;
+ box-shadow: 0 -1px 0 #bbb inset;
}
h1 {
@@ -187,7 +187,7 @@ body {
}
.page-title-empty {
- margin-top: 0px;
+ margin-top: 0;
line-height: 1.3;
font-size: 1.25em;
font-weight: 600;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index d491d01a3cf..be626678bd7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -1,53 +1,83 @@
-$row-hover: #f4f8fe;
-$gl-text-color: #54565B;
-$gl-text-green: #4A2;
-$gl-text-red: #D12F19;
-$gl-text-orange: #D90;
-$gl-header-color: #323232;
-$gl-link-color: #333c48;
-$md-text-color: #444;
-$md-link-color: #3084bb;
-$progress-color: #c0392b;
-$gl-font-size: 15px;
-$list-font-size: 15px;
+/*
+ * Layout
+ */
$sidebar_collapsed_width: 62px;
$sidebar_width: 230px;
$gutter_collapsed_width: 62px;
$gutter_width: 290px;
$gutter_inner_width: 258px;
-$avatar_radius: 50%;
+
+/*
+ * UI elements
+ */
+$border-color: #efeff1;
+$table-border-color: #eef0f2;
+$background-color: #faf9f9;
+
+/*
+ * Text
+ */
+$gl-font-size: 15px;
+$gl-title-color: #333;
+$gl-text-color: #555;
+$gl-text-green: #4a2;
+$gl-text-red: #d12f19;
+$gl-text-orange: #d90;
+$gl-link-color: #3084bb;
+$gl-dark-link-color: #333;
+$gl-placeholder-color: #8f8f8f;
+$gl-gray: $gl-text-color;
+$gl-header-color: $gl-title-color;
+
+/*
+ * Lists
+ */
+$list-font-size: $gl-font-size;
+$list-title-color: $gl-title-color;
+$list-text-color: $gl-text-color;
+
+/*
+ * Markdown
+ */
+$md-text-color: $gl-text-color;
+$md-link-color: $gl-link-color;
+
+/*
+ * Code
+ */
$code_font_size: 13px;
$code_line_height: 1.5;
-$border-color: #efeff1;
-$table-border-color: #eef0f2;
-$background-color: #faf9f9;
-$header-height: 58px;
-$fixed-layout-width: 1280px;
-$gl-gray: #5a5a5a;
+
+/*
+ * Padding
+ */
$gl-padding: 16px;
$gl-btn-padding: 10px;
$gl-vert-padding: 6px;
-$gl-padding-top:10px;
+$gl-padding-top: 10px;
+
+/*
+ * Misc
+ */
+$row-hover: #f4f8fe;
+$progress-color: #c0392b;
+$avatar_radius: 50%;
+$header-height: 58px;
+$fixed-layout-width: 1280px;
$gl-avatar-size: 40px;
-$secondary-text: #7f8fa4;
-$error-exclamation-point: #E62958;
+$error-exclamation-point: #e62958;
$border-radius-default: 3px;
-$list-title-color: #333333;
-$list-text-color: #555555;
-
-$btn-transparent-color: #8F8F8F;
-
-$ssh-key-icon-color: #8F8F8F;
+$btn-transparent-color: #8f8f8f;
+$ssh-key-icon-color: #8f8f8f;
$ssh-key-icon-size: 18px;
-
-$provider-btn-group-border: #E5E5E5;
-$provider-btn-not-active-color: #4688F1;
+$provider-btn-group-border: #e5e5e5;
+$provider-btn-not-active-color: #4688f1;
/*
* Color schema
*/
-$white-light: #FFFFFF;
+$white-light: #fff;
$white-normal: #ededed;
$white-dark: #ededed;
@@ -57,55 +87,55 @@ $gray-dark: #ededed;
$gray-darkest: #c9c9c9;
$green-light: #38ae67;
-$green-normal: #2FAA60;
-$green-dark: #2CA05B;
+$green-normal: #2faa60;
+$green-dark: #2ca05b;
-$blue-light: #2EA8E5;
-$blue-normal: #2D9FD8;
-$blue-dark: #2897CE;
+$blue-light: #2ea8e5;
+$blue-normal: #2d9fd8;
+$blue-dark: #2897ce;
-$blue-medium-light: #3498CB;
-$blue-medium: #2F8EBF;
-$blue-medium-dark: #2D86B4;
+$blue-medium-light: #3498cb;
+$blue-medium: #2f8ebf;
+$blue-medium-dark: #2d86b4;
$orange-light: rgba(252, 109, 38, 0.80);
-$orange-normal: #E75E40;
-$orange-dark: #CE5237;
+$orange-normal: #e75e40;
+$orange-dark: #ce5237;
-$red-light: #F06559;
-$red-normal: #E52C5A;
-$red-dark: #D22852;
+$red-light: #f06559;
+$red-normal: #e52c5a;
+$red-dark: #d22852;
-$border-white-light: #F1F2F4;
-$border-white-normal: #D6DAE2;
-$border-white-dark: #C6CACF;
+$border-white-light: #f1f2f4;
+$border-white-normal: #d6dae2;
+$border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06);
$border-gray-normal: rgba(0, 0, 0, 0.10);;
-$border-gray-dark: #C6CACF;
+$border-gray-dark: #c6cacf;
-$border-green-light: #2FAA60;
-$border-green-normal: #2CA05B;
+$border-green-light: #2faa60;
+$border-green-normal: #2ca05b;
$border-green-dark: #279654;
-$border-blue-light: #2D9FD8;
-$border-blue-normal: #2897CE;
-$border-blue-dark: #258DC1;
+$border-blue-light: #2d9fd8;
+$border-blue-normal: #2897ce;
+$border-blue-dark: #258dc1;
$border-orange-light: #fc6d26;
-$border-orange-normal: #CE5237;
-$border-orange-dark: #C14E35;
+$border-orange-normal: #ce5237;
+$border-orange-dark: #c14e35;
-$border-red-light: #F24F41;
-$border-red-normal: #D22852;
-$border-red-dark: #CA264F;
+$border-red-light: #f24f41;
+$border-red-normal: #d22852;
+$border-red-dark: #ca264f;
-$help-well-bg: #FAFAFA;
-$help-well-border: #E5E5E5;
+$help-well-bg: #fafafa;
+$help-well-border: #e5e5e5;
-$warning-message-bg: #FBF2D9;
-$warning-message-color: #9E8E60;
-$warning-message-border: #F0E2BB;
+$warning-message-bg: #fbf2d9;
+$warning-message-color: #9e8e60;
+$warning-message-border: #f0e2bb;
/* header */
$light-grey-header: #faf9f9;
@@ -143,23 +173,22 @@ $dropdown-border-color: rgba(#000, .1);
$dropdown-shadow-color: rgba(#000, .1);
$dropdown-divider-color: rgba(#000, .1);
$dropdown-header-color: #959494;
-$dropdown-caret-color: #54565B;
-$dropdown-title-btn-color: #BFBFBF;
-$dropdown-input-color: #C7C7C7;
+$dropdown-title-btn-color: #bfbfbf;
+$dropdown-input-color: #c7c7c7;
$dropdown-input-focus-border: rgb(58, 171, 240);
$dropdown-input-focus-shadow: rgba(#000, .2);
$dropdown-loading-bg: rgba(#fff, .6);
$dropdown-toggle-bg: #fff;
$dropdown-toggle-color: #626262;
-$dropdown-toggle-border-color: #EAEAEA;
+$dropdown-toggle-border-color: #eaeaea;
$dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%);
-$dropdown-toggle-icon-color: #C4C4C4;
+$dropdown-toggle-icon-color: #c4c4c4;
$dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
/*
* Award emoji
*/
-$award-emoji-menu-bg: #FFF;
-$award-emoji-menu-border: #F1F2F4;
-$award-emoji-new-btn-icon-color: #DCDCDC;
+$award-emoji-menu-bg: #fff;
+$award-emoji-menu-border: #f1f2f4;
+$award-emoji-new-btn-icon-color: #dcdcdc;
diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss
index c3f27333fad..02e24ec7c4d 100644
--- a/app/assets/stylesheets/framework/zen.scss
+++ b/app/assets/stylesheets/framework/zen.scss
@@ -2,7 +2,7 @@
a.js-zen-enter {
color: $gl-gray;
position: absolute;
- top: 0px;
+ top: 0;
right: 4px;
line-height: 56px;
}
diff --git a/app/assets/stylesheets/highlight/dark.scss b/app/assets/stylesheets/highlight/dark.scss
index b794da2ce98..47673944896 100644
--- a/app/assets/stylesheets/highlight/dark.scss
+++ b/app/assets/stylesheets/highlight/dark.scss
@@ -43,12 +43,12 @@
// Search result highlight
span.highlight_word {
background-color: #ffe792 !important;
- color: #000000 !important;
+ color: #000 !important;
}
.hll { background-color: #373b41 }
.c { color: #969896 } /* Comment */
- .err { color: #cc6666 } /* Error */
+ .err { color: #c66 } /* Error */
.k { color: #b294bb } /* Keyword */
.l { color: #de935f } /* Literal */
.n { color: #c5c8c6 } /* Name */
@@ -58,7 +58,7 @@
.cp { color: #969896 } /* Comment.Preproc */
.c1 { color: #969896 } /* Comment.Single */
.cs { color: #969896 } /* Comment.Special */
- .gd { color: #cc6666 } /* Generic.Deleted */
+ .gd { color: #c66 } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gh { color: #c5c8c6; font-weight: bold } /* Generic.Heading */
.gi { color: #b5bd68 } /* Generic.Inserted */
@@ -77,17 +77,17 @@
.na { color: #81a2be } /* Name.Attribute */
.nb { color: #c5c8c6 } /* Name.Builtin */
.nc { color: #f0c674 } /* Name.Class */
- .no { color: #cc6666 } /* Name.Constant */
+ .no { color: #c66 } /* Name.Constant */
.nd { color: #8abeb7 } /* Name.Decorator */
.ni { color: #c5c8c6 } /* Name.Entity */
- .ne { color: #cc6666 } /* Name.Exception */
+ .ne { color: #c66 } /* Name.Exception */
.nf { color: #81a2be } /* Name.Function */
.nl { color: #c5c8c6 } /* Name.Label */
.nn { color: #f0c674 } /* Name.Namespace */
.nx { color: #81a2be } /* Name.Other */
.py { color: #c5c8c6 } /* Name.Property */
.nt { color: #8abeb7 } /* Name.Tag */
- .nv { color: #cc6666 } /* Name.Variable */
+ .nv { color: #c66 } /* Name.Variable */
.ow { color: #8abeb7 } /* Operator.Word */
.w { color: #c5c8c6 } /* Text.Whitespace */
.mf { color: #de935f } /* Literal.Number.Float */
@@ -106,8 +106,8 @@
.s1 { color: #b5bd68 } /* Literal.String.Single */
.ss { color: #b5bd68 } /* Literal.String.Symbol */
.bp { color: #c5c8c6 } /* Name.Builtin.Pseudo */
- .vc { color: #cc6666 } /* Name.Variable.Class */
- .vg { color: #cc6666 } /* Name.Variable.Global */
- .vi { color: #cc6666 } /* Name.Variable.Instance */
+ .vc { color: #c66 } /* Name.Variable.Class */
+ .vg { color: #c66 } /* Name.Variable.Global */
+ .vi { color: #c66 } /* Name.Variable.Instance */
.il { color: #de935f } /* Literal.Number.Integer.Long */
}
diff --git a/app/assets/stylesheets/highlight/monokai.scss b/app/assets/stylesheets/highlight/monokai.scss
index 9098e07adcd..806401c21ae 100644
--- a/app/assets/stylesheets/highlight/monokai.scss
+++ b/app/assets/stylesheets/highlight/monokai.scss
@@ -43,7 +43,7 @@
// Search result highlight
span.highlight_word {
background-color: #ffe792 !important;
- color: #000000 !important;
+ color: #000 !important;
}
.hll { background-color: #49483e }
diff --git a/app/assets/stylesheets/highlight/solarized_dark.scss b/app/assets/stylesheets/highlight/solarized_dark.scss
index 8b1a2824f76..6a809d4dfd2 100644
--- a/app/assets/stylesheets/highlight/solarized_dark.scss
+++ b/app/assets/stylesheets/highlight/solarized_dark.scss
@@ -96,7 +96,7 @@
.m { color: #2aa198 } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */
.na { color: #93a1a1 } /* Name.Attribute */
- .nb { color: #B58900 } /* Name.Builtin */
+ .nb { color: #b58900 } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */
diff --git a/app/assets/stylesheets/highlight/solarized_light.scss b/app/assets/stylesheets/highlight/solarized_light.scss
index 7ad89dd2c7c..b90c95c62d1 100644
--- a/app/assets/stylesheets/highlight/solarized_light.scss
+++ b/app/assets/stylesheets/highlight/solarized_light.scss
@@ -96,7 +96,7 @@
.m { color: #2aa198 } /* Literal.Number */
.s { color: #2aa198 } /* Literal.String */
.na { color: #586e75 } /* Name.Attribute */
- .nb { color: #B58900 } /* Name.Builtin */
+ .nb { color: #b58900 } /* Name.Builtin */
.nc { color: #268bd2 } /* Name.Class */
.no { color: #cb4b16 } /* Name.Constant */
.nd { color: #268bd2 } /* Name.Decorator */
diff --git a/app/assets/stylesheets/highlight/white.scss b/app/assets/stylesheets/highlight/white.scss
index 8a091028a6c..8c1b0cd84ec 100644
--- a/app/assets/stylesheets/highlight/white.scss
+++ b/app/assets/stylesheets/highlight/white.scss
@@ -23,7 +23,7 @@
.line_holder {
.diff-line-num {
&.old {
- background: #ffdddd;
+ background: #fdd;
border-color: #f1c0c0;
}
@@ -68,66 +68,66 @@
}
.hll { background-color: #f8f8f8 }
- .c { color: #999988; font-style: italic; }
+ .c { color: #998; font-style: italic; }
.err { color: #a61717; background-color: #e3d2d2; }
.k { font-weight: bold; }
.o { font-weight: bold; }
- .cm { color: #999988; font-style: italic; }
- .cp { color: #999999; font-weight: bold; }
- .c1 { color: #999988; font-style: italic; }
- .cs { color: #999999; font-weight: bold; font-style: italic; }
- .gd { color: #000000; background-color: #ffdddd; }
- .gd .x { color: #000000; background-color: #ffaaaa; }
+ .cm { color: #998; font-style: italic; }
+ .cp { color: #999; font-weight: bold; }
+ .c1 { color: #998; font-style: italic; }
+ .cs { color: #999; font-weight: bold; font-style: italic; }
+ .gd { color: #000; background-color: #fdd; }
+ .gd .x { color: #000; background-color: #faa; }
.ge { font-style: italic; }
- .gr { color: #aa0000; }
- .gh { color: #999999; }
- .gi { color: #000000; background-color: #ddffdd; }
- .gi .x { color: #000000; background-color: #aaffaa; }
- .go { color: #888888; }
- .gp { color: #555555; }
+ .gr { color: #a00; }
+ .gh { color: #999; }
+ .gi { color: #000; background-color: #dfd; }
+ .gi .x { color: #000; background-color: #afa; }
+ .go { color: #888; }
+ .gp { color: #555; }
.gs { font-weight: bold; }
.gu { color: #800080; font-weight: bold; }
- .gt { color: #aa0000; }
+ .gt { color: #a00; }
.kc { font-weight: bold; }
.kd { font-weight: bold; }
.kn { font-weight: bold; }
.kp { font-weight: bold; }
.kr { font-weight: bold; }
- .kt { color: #445588; font-weight: bold; }
- .m { color: #009999; }
- .s { color: #dd1144; }
- .n { color: #333333; }
+ .kt { color: #458; font-weight: bold; }
+ .m { color: #099; }
+ .s { color: #d14; }
+ .n { color: #333; }
.na { color: teal; }
.nb { color: #0086b3; }
- .nc { color: #445588; font-weight: bold; }
+ .nc { color: #458; font-weight: bold; }
.no { color: teal; }
.ni { color: purple; }
- .ne { color: #990000; font-weight: bold; }
- .nf { color: #990000; font-weight: bold; }
- .nn { color: #555555; }
+ .ne { color: #900; font-weight: bold; }
+ .nf { color: #900; font-weight: bold; }
+ .nn { color: #555; }
.nt { color: navy; }
.nv { color: teal; }
.ow { font-weight: bold; }
- .w { color: #bbbbbb; }
- .mf { color: #009999; }
- .mh { color: #009999; }
- .mi { color: #009999; }
- .mo { color: #009999; }
- .sb { color: #dd1144; }
- .sc { color: #dd1144; }
- .sd { color: #dd1144; }
- .s2 { color: #dd1144; }
- .se { color: #dd1144; }
- .sh { color: #dd1144; }
- .si { color: #dd1144; }
- .sx { color: #dd1144; }
+ .w { color: #bbb; }
+ .mf { color: #099; }
+ .mh { color: #099; }
+ .mi { color: #099; }
+ .mo { color: #099; }
+ .sb { color: #d14; }
+ .sc { color: #d14; }
+ .sd { color: #d14; }
+ .s2 { color: #d14; }
+ .se { color: #d14; }
+ .sh { color: #d14; }
+ .si { color: #d14; }
+ .sx { color: #d14; }
.sr { color: #009926; }
- .s1 { color: #dd1144; }
+ .s1 { color: #d14; }
.ss { color: #990073; }
- .bp { color: #999999; }
+ .bp { color: #999; }
.vc { color: teal; }
.vg { color: teal; }
.vi { color: teal; }
- .il { color: #009999; }
- .gc { color: #999; background-color: #EAF2F5; }
+ .il { color: #099; }
+ .gc { color: #999; background-color: #eaf2f5; }
}
diff --git a/app/assets/stylesheets/pages/appearances.scss b/app/assets/stylesheets/pages/appearances.scss
index e2070f17c3b..878f44116ba 100644
--- a/app/assets/stylesheets/pages/appearances.scss
+++ b/app/assets/stylesheets/pages/appearances.scss
@@ -4,7 +4,7 @@
}
.appearance-light-logo-preview {
- background-color: $background-color;
+ background-color: $background-color;
max-width: 72px;
padding: 10px;
margin-bottom: 10px;
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 75f298019e3..201f3e5ca46 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -1,6 +1,6 @@
.build-page {
pre.trace {
- background: #111111;
+ background: #111;
color: #fff;
font-family: $monospace_font;
white-space: pre;
diff --git a/app/assets/stylesheets/pages/commit.scss b/app/assets/stylesheets/pages/commit.scss
index c0cc30d33a6..971656feb42 100644
--- a/app/assets/stylesheets/pages/commit.scss
+++ b/app/assets/stylesheets/pages/commit.scss
@@ -55,7 +55,7 @@
padding: 10px 0;
li {
- padding: 3px 0px;
+ padding: 3px 0;
line-height: 20px;
}
}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 818fd03e2ae..33b3c7558ed 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -9,7 +9,7 @@
.lists-separator {
margin: 10px 0;
- border-color: #DDD;
+ border-color: #ddd;
}
.commits-row {
@@ -55,7 +55,7 @@ li.commit {
}
.commit-row-message {
- color: $gl-link-color;
+ color: $gl-dark-link-color;
&:hover {
text-decoration: underline;
@@ -76,7 +76,7 @@ li.commit {
.commit-row-description {
font-size: 14px;
- border-left: 1px solid #EEE;
+ border-left: 1px solid #eee;
padding: 10px 15px;
margin: 5px 0 10px 5px;
background: #f9f9f9;
@@ -152,7 +152,7 @@ li.commit {
.count {
padding-top: 6px;
- padding-bottom: 0px;
+ padding-bottom: 0;
font-size: 12px;
color: #333;
display: block;
diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss
index 88639399148..cf7567513ec 100644
--- a/app/assets/stylesheets/pages/dashboard.scss
+++ b/app/assets/stylesheets/pages/dashboard.scss
@@ -11,15 +11,15 @@
}
.dashboard-search-filter {
- padding:5px;
+ padding: 5px;
.search-text-input {
- float:left;
+ float: left;
@extend .col-md-2;
}
.btn {
margin-left: 5px;
- float:left;
+ float: left;
}
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index a7925e79549..d5862a11aca 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -1,7 +1,7 @@
// Common
.diff-file {
border: 1px solid $border-color;
- border-top: none;
+ margin-bottom: $gl-padding;
.diff-header {
position: relative;
@@ -29,7 +29,7 @@
.diff-content {
overflow: auto;
overflow-y: hidden;
- background: #FFF;
+ background: #fff;
color: #333;
.unfold {
@@ -57,8 +57,8 @@
font-family: $monospace_font;
border: none;
border-collapse: separate;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
.line_holder td {
line-height: $code_line_height;
font-size: $code_font_size;
@@ -76,10 +76,10 @@
}
.old_line, .new_line {
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
border: none;
- padding: 0px 5px;
+ padding: 0 5px;
border-right: 1px solid;
text-align: right;
min-width: 35px;
@@ -97,8 +97,8 @@
}
.line_content {
display: block;
- margin: 0px;
- padding: 0px 0.5em;
+ margin: 0;
+ padding: 0 0.5em;
border: none;
&.parallel {
display: table-cell;
@@ -118,7 +118,7 @@
background-color: #fff;
line-height: 0;
img {
- border: 1px solid #FFF;
+ border: 1px solid #fff;
background: image-url('trans_bg.gif');
max-width: 100%;
}
@@ -183,7 +183,7 @@
height: 14px;
width: 15px;
position: absolute;
- top: 0px;
+ top: 0;
background: image-url('swipemode_sprites.gif') 0 3px no-repeat;
}
.bottom-handle {
@@ -191,7 +191,7 @@
height: 14px;
width: 15px;
position: absolute;
- bottom: 0px;
+ bottom: 0;
background: image-url('swipemode_sprites.gif') 0 -11px no-repeat;
}
}
@@ -206,8 +206,8 @@
.frame.added, .frame.deleted {
position: absolute;
display: block;
- top: 0px;
- left: 0px;
+ top: 0;
+ left: 0;
}
.controls {
display: block;
@@ -215,7 +215,7 @@
width: 300px;
z-index: 100;
position: absolute;
- bottom: 0px;
+ bottom: 0;
left: 50%;
margin-left: -150px;
@@ -231,11 +231,11 @@
.dragger {
display: block;
position: absolute;
- left: 0px;
- top: 0px;
+ left: 0;
+ top: 0;
height: 14px;
width: 14px;
- background: image-url('onion_skin_sprites.gif') 0px -34px repeat-x;
+ background: image-url('onion_skin_sprites.gif') 0 -34px repeat-x;
cursor: pointer;
}
@@ -243,17 +243,17 @@
display: block;
position: absolute;
top: 2px;
- right: 0px;
+ right: 0;
height: 10px;
width: 10px;
- background: image-url('onion_skin_sprites.gif') -2px 0px no-repeat;
+ background: image-url('onion_skin_sprites.gif') -2px 0 no-repeat;
}
.opaque {
display: block;
position: absolute;
top: 2px;
- left: 0px;
+ left: 0;
height: 10px;
width: 10px;
background: image-url('onion_skin_sprites.gif') -2px -10px no-repeat;
@@ -265,7 +265,7 @@
.view-modes {
padding: 10px;
text-align: center;
- background: #EEE;
+ background: #eee;
ul, li {
list-style: none;
@@ -361,3 +361,11 @@
border-color: $border;
}
}
+
+.files {
+ margin-top: -1px;
+
+ .diff-file:last-child {
+ margin-bottom: 0;
+ }
+}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 39d916cd336..43be5e38ba8 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -14,9 +14,9 @@
}
.cancel-btn {
- color: #B94A48;
+ color: #b94a48;
&:hover {
- color: #B94A48;
+ color: #b94a48;
}
}
diff --git a/app/assets/stylesheets/pages/emojis.scss b/app/assets/stylesheets/pages/emojis.scss
index 6c721b514f8..b731abc7450 100644
--- a/app/assets/stylesheets/pages/emojis.scss
+++ b/app/assets/stylesheets/pages/emojis.scss
@@ -1,60 +1,60 @@
-.emoji-0023-20E3 { background-position: 0px 0px; }
-.emoji-002A-20E3 { background-position: -20px 0px; }
-.emoji-0030-20E3 { background-position: 0px -20px; }
+.emoji-0023-20E3 { background-position: 0 0; }
+.emoji-002A-20E3 { background-position: -20px 0; }
+.emoji-0030-20E3 { background-position: 0 -20px; }
.emoji-0031-20E3 { background-position: -20px -20px; }
-.emoji-0032-20E3 { background-position: -40px 0px; }
+.emoji-0032-20E3 { background-position: -40px 0; }
.emoji-0033-20E3 { background-position: -40px -20px; }
-.emoji-0034-20E3 { background-position: 0px -40px; }
+.emoji-0034-20E3 { background-position: 0 -40px; }
.emoji-0035-20E3 { background-position: -20px -40px; }
.emoji-0036-20E3 { background-position: -40px -40px; }
-.emoji-0037-20E3 { background-position: -60px 0px; }
+.emoji-0037-20E3 { background-position: -60px 0; }
.emoji-0038-20E3 { background-position: -60px -20px; }
.emoji-0039-20E3 { background-position: -60px -40px; }
-.emoji-00A9 { background-position: 0px -60px; }
+.emoji-00A9 { background-position: 0 -60px; }
.emoji-00AE { background-position: -20px -60px; }
.emoji-1F004 { background-position: -40px -60px; }
.emoji-1F0CF { background-position: -60px -60px; }
-.emoji-1F170 { background-position: -80px 0px; }
+.emoji-1F170 { background-position: -80px 0; }
.emoji-1F171 { background-position: -80px -20px; }
.emoji-1F17E { background-position: -80px -40px; }
.emoji-1F17F { background-position: -80px -60px; }
-.emoji-1F18E { background-position: 0px -80px; }
+.emoji-1F18E { background-position: 0 -80px; }
.emoji-1F191 { background-position: -20px -80px; }
.emoji-1F192 { background-position: -40px -80px; }
.emoji-1F193 { background-position: -60px -80px; }
.emoji-1F194 { background-position: -80px -80px; }
-.emoji-1F195 { background-position: -100px 0px; }
+.emoji-1F195 { background-position: -100px 0; }
.emoji-1F196 { background-position: -100px -20px; }
.emoji-1F197 { background-position: -100px -40px; }
.emoji-1F198 { background-position: -100px -60px; }
.emoji-1F199 { background-position: -100px -80px; }
-.emoji-1F19A { background-position: 0px -100px; }
+.emoji-1F19A { background-position: 0 -100px; }
.emoji-1F1E6-1F1E8 { background-position: -20px -100px; }
.emoji-1F1E6-1F1E9 { background-position: -40px -100px; }
.emoji-1F1E6-1F1EA { background-position: -60px -100px; }
.emoji-1F1E6-1F1EB { background-position: -80px -100px; }
.emoji-1F1E6-1F1EC { background-position: -100px -100px; }
-.emoji-1F1E6-1F1EE { background-position: -120px 0px; }
+.emoji-1F1E6-1F1EE { background-position: -120px 0; }
.emoji-1F1E6-1F1F1 { background-position: -120px -20px; }
.emoji-1F1E6-1F1F2 { background-position: -120px -40px; }
.emoji-1F1E6-1F1F4 { background-position: -120px -60px; }
.emoji-1F1E6-1F1F6 { background-position: -120px -80px; }
.emoji-1F1E6-1F1F7 { background-position: -120px -100px; }
-.emoji-1F1E6-1F1F8 { background-position: 0px -120px; }
+.emoji-1F1E6-1F1F8 { background-position: 0 -120px; }
.emoji-1F1E6-1F1F9 { background-position: -20px -120px; }
.emoji-1F1E6-1F1FA { background-position: -40px -120px; }
.emoji-1F1E6-1F1FC { background-position: -60px -120px; }
.emoji-1F1E6-1F1FD { background-position: -80px -120px; }
.emoji-1F1E6-1F1FF { background-position: -100px -120px; }
.emoji-1F1E7-1F1E6 { background-position: -120px -120px; }
-.emoji-1F1E7-1F1E7 { background-position: -140px 0px; }
+.emoji-1F1E7-1F1E7 { background-position: -140px 0; }
.emoji-1F1E7-1F1E9 { background-position: -140px -20px; }
.emoji-1F1E7-1F1EA { background-position: -140px -40px; }
.emoji-1F1E7-1F1EB { background-position: -140px -60px; }
.emoji-1F1E7-1F1EC { background-position: -140px -80px; }
.emoji-1F1E7-1F1ED { background-position: -140px -100px; }
.emoji-1F1E7-1F1EE { background-position: -140px -120px; }
-.emoji-1F1E7-1F1EF { background-position: 0px -140px; }
+.emoji-1F1E7-1F1EF { background-position: 0 -140px; }
.emoji-1F1E7-1F1F1 { background-position: -20px -140px; }
.emoji-1F1E7-1F1F2 { background-position: -40px -140px; }
.emoji-1F1E7-1F1F3 { background-position: -60px -140px; }
@@ -62,7 +62,7 @@
.emoji-1F1E7-1F1F6 { background-position: -100px -140px; }
.emoji-1F1E7-1F1F7 { background-position: -120px -140px; }
.emoji-1F1E7-1F1F8 { background-position: -140px -140px; }
-.emoji-1F1E7-1F1F9 { background-position: -160px 0px; }
+.emoji-1F1E7-1F1F9 { background-position: -160px 0; }
.emoji-1F1E7-1F1FB { background-position: -160px -20px; }
.emoji-1F1E7-1F1FC { background-position: -160px -40px; }
.emoji-1F1E7-1F1FE { background-position: -160px -60px; }
@@ -70,7 +70,7 @@
.emoji-1F1E8-1F1E6 { background-position: -160px -100px; }
.emoji-1F1E8-1F1E8 { background-position: -160px -120px; }
.emoji-1F1E8-1F1E9 { background-position: -160px -140px; }
-.emoji-1F1E8-1F1EB { background-position: 0px -160px; }
+.emoji-1F1E8-1F1EB { background-position: 0 -160px; }
.emoji-1F1E8-1F1EC { background-position: -20px -160px; }
.emoji-1F1E8-1F1ED { background-position: -40px -160px; }
.emoji-1F1E8-1F1EE { background-position: -60px -160px; }
@@ -79,7 +79,7 @@
.emoji-1F1E8-1F1F2 { background-position: -120px -160px; }
.emoji-1F1E8-1F1F3 { background-position: -140px -160px; }
.emoji-1F1E8-1F1F4 { background-position: -160px -160px; }
-.emoji-1F1E8-1F1F5 { background-position: -180px 0px; }
+.emoji-1F1E8-1F1F5 { background-position: -180px 0; }
.emoji-1F1E8-1F1F7 { background-position: -180px -20px; }
.emoji-1F1E8-1F1FA { background-position: -180px -40px; }
.emoji-1F1E8-1F1FB { background-position: -180px -60px; }
@@ -88,7 +88,7 @@
.emoji-1F1E8-1F1FE { background-position: -180px -120px; }
.emoji-1F1E8-1F1FF { background-position: -180px -140px; }
.emoji-1F1E9-1F1EA { background-position: -180px -160px; }
-.emoji-1F1E9-1F1EC { background-position: 0px -180px; }
+.emoji-1F1E9-1F1EC { background-position: 0 -180px; }
.emoji-1F1E9-1F1EF { background-position: -20px -180px; }
.emoji-1F1E9-1F1F0 { background-position: -40px -180px; }
.emoji-1F1E9-1F1F2 { background-position: -60px -180px; }
@@ -98,7 +98,7 @@
.emoji-1F1EA-1F1E8 { background-position: -140px -180px; }
.emoji-1F1EA-1F1EA { background-position: -160px -180px; }
.emoji-1F1EA-1F1EC { background-position: -180px -180px; }
-.emoji-1F1EA-1F1ED { background-position: -200px 0px; }
+.emoji-1F1EA-1F1ED { background-position: -200px 0; }
.emoji-1F1EA-1F1F7 { background-position: -200px -20px; }
.emoji-1F1EA-1F1F8 { background-position: -200px -40px; }
.emoji-1F1EA-1F1F9 { background-position: -200px -60px; }
@@ -108,7 +108,7 @@
.emoji-1F1EB-1F1F0 { background-position: -200px -140px; }
.emoji-1F1EB-1F1F2 { background-position: -200px -160px; }
.emoji-1F1EB-1F1F4 { background-position: -200px -180px; }
-.emoji-1F1EB-1F1F7 { background-position: 0px -200px; }
+.emoji-1F1EB-1F1F7 { background-position: 0 -200px; }
.emoji-1F1EC-1F1E6 { background-position: -20px -200px; }
.emoji-1F1EC-1F1E7 { background-position: -40px -200px; }
.emoji-1F1EC-1F1E9 { background-position: -60px -200px; }
@@ -119,7 +119,7 @@
.emoji-1F1EC-1F1EE { background-position: -160px -200px; }
.emoji-1F1EC-1F1F1 { background-position: -180px -200px; }
.emoji-1F1EC-1F1F2 { background-position: -200px -200px; }
-.emoji-1F1EC-1F1F3 { background-position: -220px 0px; }
+.emoji-1F1EC-1F1F3 { background-position: -220px 0; }
.emoji-1F1EC-1F1F5 { background-position: -220px -20px; }
.emoji-1F1EC-1F1F6 { background-position: -220px -40px; }
.emoji-1F1EC-1F1F7 { background-position: -220px -60px; }
@@ -130,7 +130,7 @@
.emoji-1F1EC-1F1FE { background-position: -220px -160px; }
.emoji-1F1ED-1F1F0 { background-position: -220px -180px; }
.emoji-1F1ED-1F1F2 { background-position: -220px -200px; }
-.emoji-1F1ED-1F1F3 { background-position: 0px -220px; }
+.emoji-1F1ED-1F1F3 { background-position: 0 -220px; }
.emoji-1F1ED-1F1F7 { background-position: -20px -220px; }
.emoji-1F1ED-1F1F9 { background-position: -40px -220px; }
.emoji-1F1ED-1F1FA { background-position: -60px -220px; }
@@ -142,7 +142,7 @@
.emoji-1F1EE-1F1F3 { background-position: -180px -220px; }
.emoji-1F1EE-1F1F4 { background-position: -200px -220px; }
.emoji-1F1EE-1F1F6 { background-position: -220px -220px; }
-.emoji-1F1EE-1F1F7 { background-position: -240px 0px; }
+.emoji-1F1EE-1F1F7 { background-position: -240px 0; }
.emoji-1F1EE-1F1F8 { background-position: -240px -20px; }
.emoji-1F1EE-1F1F9 { background-position: -240px -40px; }
.emoji-1F1EF-1F1EA { background-position: -240px -60px; }
@@ -154,7 +154,7 @@
.emoji-1F1F0-1F1ED { background-position: -240px -180px; }
.emoji-1F1F0-1F1EE { background-position: -240px -200px; }
.emoji-1F1F0-1F1F2 { background-position: -240px -220px; }
-.emoji-1F1F0-1F1F3 { background-position: 0px -240px; }
+.emoji-1F1F0-1F1F3 { background-position: 0 -240px; }
.emoji-1F1F0-1F1F5 { background-position: -20px -240px; }
.emoji-1F1F0-1F1F7 { background-position: -40px -240px; }
.emoji-1F1F0-1F1FC { background-position: -60px -240px; }
@@ -167,7 +167,7 @@
.emoji-1F1F1-1F1F0 { background-position: -200px -240px; }
.emoji-1F1F1-1F1F7 { background-position: -220px -240px; }
.emoji-1F1F1-1F1F8 { background-position: -240px -240px; }
-.emoji-1F1F1-1F1F9 { background-position: -260px 0px; }
+.emoji-1F1F1-1F1F9 { background-position: -260px 0; }
.emoji-1F1F1-1F1FA { background-position: -260px -20px; }
.emoji-1F1F1-1F1FB { background-position: -260px -40px; }
.emoji-1F1F1-1F1FE { background-position: -260px -60px; }
@@ -180,7 +180,7 @@
.emoji-1F1F2-1F1ED { background-position: -260px -200px; }
.emoji-1F1F2-1F1F0 { background-position: -260px -220px; }
.emoji-1F1F2-1F1F1 { background-position: -260px -240px; }
-.emoji-1F1F2-1F1F2 { background-position: 0px -260px; }
+.emoji-1F1F2-1F1F2 { background-position: 0 -260px; }
.emoji-1F1F2-1F1F3 { background-position: -20px -260px; }
.emoji-1F1F2-1F1F4 { background-position: -40px -260px; }
.emoji-1F1F2-1F1F5 { background-position: -60px -260px; }
@@ -194,7 +194,7 @@
.emoji-1F1F2-1F1FD { background-position: -220px -260px; }
.emoji-1F1F2-1F1FE { background-position: -240px -260px; }
.emoji-1F1F2-1F1FF { background-position: -260px -260px; }
-.emoji-1F1F3-1F1E6 { background-position: -280px 0px; }
+.emoji-1F1F3-1F1E6 { background-position: -280px 0; }
.emoji-1F1F3-1F1E8 { background-position: -280px -20px; }
.emoji-1F1F3-1F1EA { background-position: -280px -40px; }
.emoji-1F1F3-1F1EB { background-position: -280px -60px; }
@@ -208,7 +208,7 @@
.emoji-1F1F3-1F1FF { background-position: -280px -220px; }
.emoji-1F1F4-1F1F2 { background-position: -280px -240px; }
.emoji-1F1F5-1F1E6 { background-position: -280px -260px; }
-.emoji-1F1F5-1F1EA { background-position: 0px -280px; }
+.emoji-1F1F5-1F1EA { background-position: 0 -280px; }
.emoji-1F1F5-1F1EB { background-position: -20px -280px; }
.emoji-1F1F5-1F1EC { background-position: -40px -280px; }
.emoji-1F1F5-1F1ED { background-position: -60px -280px; }
@@ -223,7 +223,7 @@
.emoji-1F1F5-1F1FE { background-position: -240px -280px; }
.emoji-1F1F6-1F1E6 { background-position: -260px -280px; }
.emoji-1F1F7-1F1EA { background-position: -280px -280px; }
-.emoji-1F1F7-1F1F4 { background-position: -300px 0px; }
+.emoji-1F1F7-1F1F4 { background-position: -300px 0; }
.emoji-1F1F7-1F1F8 { background-position: -300px -20px; }
.emoji-1F1F7-1F1FA { background-position: -300px -40px; }
.emoji-1F1F7-1F1FC { background-position: -300px -60px; }
@@ -238,7 +238,7 @@
.emoji-1F1F8-1F1EF { background-position: -300px -240px; }
.emoji-1F1F8-1F1F0 { background-position: -300px -260px; }
.emoji-1F1F8-1F1F1 { background-position: -300px -280px; }
-.emoji-1F1F8-1F1F2 { background-position: 0px -300px; }
+.emoji-1F1F8-1F1F2 { background-position: 0 -300px; }
.emoji-1F1F8-1F1F3 { background-position: -20px -300px; }
.emoji-1F1F8-1F1F4 { background-position: -40px -300px; }
.emoji-1F1F8-1F1F7 { background-position: -60px -300px; }
@@ -254,7 +254,7 @@
.emoji-1F1F9-1F1EB { background-position: -260px -300px; }
.emoji-1F1F9-1F1EC { background-position: -280px -300px; }
.emoji-1F1F9-1F1ED { background-position: -300px -300px; }
-.emoji-1F1F9-1F1EF { background-position: -320px 0px; }
+.emoji-1F1F9-1F1EF { background-position: -320px 0; }
.emoji-1F1F9-1F1F0 { background-position: -320px -20px; }
.emoji-1F1F9-1F1F1 { background-position: -320px -40px; }
.emoji-1F1F9-1F1F2 { background-position: -320px -60px; }
@@ -270,7 +270,7 @@
.emoji-1F1FA-1F1F2 { background-position: -320px -260px; }
.emoji-1F1FA-1F1F8 { background-position: -320px -280px; }
.emoji-1F1FA-1F1FE { background-position: -320px -300px; }
-.emoji-1F1FA-1F1FF { background-position: 0px -320px; }
+.emoji-1F1FA-1F1FF { background-position: 0 -320px; }
.emoji-1F1FB-1F1E6 { background-position: -20px -320px; }
.emoji-1F1FB-1F1E8 { background-position: -40px -320px; }
.emoji-1F1FB-1F1EA { background-position: -60px -320px; }
@@ -287,7 +287,7 @@
.emoji-1F1FF-1F1F2 { background-position: -280px -320px; }
.emoji-1F1FF-1F1FC { background-position: -300px -320px; }
.emoji-1F201 { background-position: -320px -320px; }
-.emoji-1F202 { background-position: -340px 0px; }
+.emoji-1F202 { background-position: -340px 0; }
.emoji-1F21A { background-position: -340px -20px; }
.emoji-1F22F { background-position: -340px -40px; }
.emoji-1F232 { background-position: -340px -60px; }
@@ -304,7 +304,7 @@
.emoji-1F300 { background-position: -340px -280px; }
.emoji-1F301 { background-position: -340px -300px; }
.emoji-1F302 { background-position: -340px -320px; }
-.emoji-1F303 { background-position: 0px -340px; }
+.emoji-1F303 { background-position: 0 -340px; }
.emoji-1F304 { background-position: -20px -340px; }
.emoji-1F305 { background-position: -40px -340px; }
.emoji-1F306 { background-position: -60px -340px; }
@@ -322,7 +322,7 @@
.emoji-1F312 { background-position: -300px -340px; }
.emoji-1F313 { background-position: -320px -340px; }
.emoji-1F314 { background-position: -340px -340px; }
-.emoji-1F315 { background-position: -360px 0px; }
+.emoji-1F315 { background-position: -360px 0; }
.emoji-1F316 { background-position: -360px -20px; }
.emoji-1F317 { background-position: -360px -40px; }
.emoji-1F318 { background-position: -360px -60px; }
@@ -340,7 +340,7 @@
.emoji-1F326 { background-position: -360px -300px; }
.emoji-1F327 { background-position: -360px -320px; }
.emoji-1F328 { background-position: -360px -340px; }
-.emoji-1F329 { background-position: 0px -360px; }
+.emoji-1F329 { background-position: 0 -360px; }
.emoji-1F32A { background-position: -20px -360px; }
.emoji-1F32B { background-position: -40px -360px; }
.emoji-1F32C { background-position: -60px -360px; }
@@ -359,7 +359,7 @@
.emoji-1F339 { background-position: -320px -360px; }
.emoji-1F33A { background-position: -340px -360px; }
.emoji-1F33B { background-position: -360px -360px; }
-.emoji-1F33C { background-position: -380px 0px; }
+.emoji-1F33C { background-position: -380px 0; }
.emoji-1F33D { background-position: -380px -20px; }
.emoji-1F33E { background-position: -380px -40px; }
.emoji-1F33F { background-position: -380px -60px; }
@@ -378,7 +378,7 @@
.emoji-1F34C { background-position: -380px -320px; }
.emoji-1F34D { background-position: -380px -340px; }
.emoji-1F34E { background-position: -380px -360px; }
-.emoji-1F34F { background-position: 0px -380px; }
+.emoji-1F34F { background-position: 0 -380px; }
.emoji-1F350 { background-position: -20px -380px; }
.emoji-1F351 { background-position: -40px -380px; }
.emoji-1F352 { background-position: -60px -380px; }
@@ -398,7 +398,7 @@
.emoji-1F360 { background-position: -340px -380px; }
.emoji-1F361 { background-position: -360px -380px; }
.emoji-1F362 { background-position: -380px -380px; }
-.emoji-1F363 { background-position: -400px 0px; }
+.emoji-1F363 { background-position: -400px 0; }
.emoji-1F364 { background-position: -400px -20px; }
.emoji-1F365 { background-position: -400px -40px; }
.emoji-1F366 { background-position: -400px -60px; }
@@ -418,7 +418,7 @@
.emoji-1F374 { background-position: -400px -340px; }
.emoji-1F375 { background-position: -400px -360px; }
.emoji-1F376 { background-position: -400px -380px; }
-.emoji-1F377 { background-position: 0px -400px; }
+.emoji-1F377 { background-position: 0 -400px; }
.emoji-1F378 { background-position: -20px -400px; }
.emoji-1F379 { background-position: -40px -400px; }
.emoji-1F37A { background-position: -60px -400px; }
@@ -439,7 +439,7 @@
.emoji-1F385-1F3FE { background-position: -360px -400px; }
.emoji-1F385-1F3FF { background-position: -380px -400px; }
.emoji-1F386 { background-position: -400px -400px; }
-.emoji-1F387 { background-position: -420px 0px; }
+.emoji-1F387 { background-position: -420px 0; }
.emoji-1F388 { background-position: -420px -20px; }
.emoji-1F389 { background-position: -420px -40px; }
.emoji-1F38A { background-position: -420px -60px; }
@@ -460,7 +460,7 @@
.emoji-1F399 { background-position: -420px -360px; }
.emoji-1F39A { background-position: -420px -380px; }
.emoji-1F39B { background-position: -420px -400px; }
-.emoji-1F39C { background-position: 0px -420px; }
+.emoji-1F39C { background-position: 0 -420px; }
.emoji-1F39D { background-position: -20px -420px; }
.emoji-1F39E { background-position: -40px -420px; }
.emoji-1F39F { background-position: -60px -420px; }
@@ -482,7 +482,7 @@
.emoji-1F3AF { background-position: -380px -420px; }
.emoji-1F3B0 { background-position: -400px -420px; }
.emoji-1F3B1 { background-position: -420px -420px; }
-.emoji-1F3B2 { background-position: -440px 0px; }
+.emoji-1F3B2 { background-position: -440px 0; }
.emoji-1F3B3 { background-position: -440px -20px; }
.emoji-1F3B4 { background-position: -440px -40px; }
.emoji-1F3B5 { background-position: -440px -60px; }
@@ -504,7 +504,7 @@
.emoji-1F3C3-1F3FC { background-position: -440px -380px; }
.emoji-1F3C3-1F3FD { background-position: -440px -400px; }
.emoji-1F3C3-1F3FE { background-position: -440px -420px; }
-.emoji-1F3C3-1F3FF { background-position: 0px -440px; }
+.emoji-1F3C3-1F3FF { background-position: 0 -440px; }
.emoji-1F3C4 { background-position: -20px -440px; }
.emoji-1F3C4-1F3FB { background-position: -40px -440px; }
.emoji-1F3C4-1F3FC { background-position: -60px -440px; }
@@ -527,7 +527,7 @@
.emoji-1F3CA-1F3FD { background-position: -400px -440px; }
.emoji-1F3CA-1F3FE { background-position: -420px -440px; }
.emoji-1F3CA-1F3FF { background-position: -440px -440px; }
-.emoji-1F3CB { background-position: -460px 0px; }
+.emoji-1F3CB { background-position: -460px 0; }
.emoji-1F3CB-1F3FB { background-position: -460px -20px; }
.emoji-1F3CB-1F3FC { background-position: -460px -40px; }
.emoji-1F3CB-1F3FD { background-position: -460px -60px; }
@@ -550,7 +550,7 @@
.emoji-1F3DA { background-position: -460px -400px; }
.emoji-1F3DB { background-position: -460px -420px; }
.emoji-1F3DC { background-position: -460px -440px; }
-.emoji-1F3DD { background-position: 0px -460px; }
+.emoji-1F3DD { background-position: 0 -460px; }
.emoji-1F3DE { background-position: -20px -460px; }
.emoji-1F3DF { background-position: -40px -460px; }
.emoji-1F3E0 { background-position: -60px -460px; }
@@ -574,7 +574,7 @@
.emoji-1F3F2 { background-position: -420px -460px; }
.emoji-1F3F3 { background-position: -440px -460px; }
.emoji-1F3F4 { background-position: -460px -460px; }
-.emoji-1F3F5 { background-position: -480px 0px; }
+.emoji-1F3F5 { background-position: -480px 0; }
.emoji-1F3F6 { background-position: -480px -20px; }
.emoji-1F3F7 { background-position: -480px -40px; }
.emoji-1F3F8 { background-position: -480px -60px; }
@@ -598,7 +598,7 @@
.emoji-1F40A { background-position: -480px -420px; }
.emoji-1F40B { background-position: -480px -440px; }
.emoji-1F40C { background-position: -480px -460px; }
-.emoji-1F40D { background-position: 0px -480px; }
+.emoji-1F40D { background-position: 0 -480px; }
.emoji-1F40E { background-position: -20px -480px; }
.emoji-1F40F { background-position: -40px -480px; }
.emoji-1F410 { background-position: -60px -480px; }
@@ -623,7 +623,7 @@
.emoji-1F423 { background-position: -440px -480px; }
.emoji-1F424 { background-position: -460px -480px; }
.emoji-1F425 { background-position: -480px -480px; }
-.emoji-1F426 { background-position: -500px 0px; }
+.emoji-1F426 { background-position: -500px 0; }
.emoji-1F427 { background-position: -500px -20px; }
.emoji-1F428 { background-position: -500px -40px; }
.emoji-1F429 { background-position: -500px -60px; }
@@ -648,7 +648,7 @@
.emoji-1F43C { background-position: -500px -440px; }
.emoji-1F43D { background-position: -500px -460px; }
.emoji-1F43E { background-position: -500px -480px; }
-.emoji-1F43F { background-position: 0px -500px; }
+.emoji-1F43F { background-position: 0 -500px; }
.emoji-1F440 { background-position: -20px -500px; }
.emoji-1F441 { background-position: -40px -500px; }
.emoji-1F441-1F5E8 { background-position: -60px -500px; }
@@ -674,7 +674,7 @@
.emoji-1F446-1F3FF { background-position: -460px -500px; }
.emoji-1F447 { background-position: -480px -500px; }
.emoji-1F447-1F3FB { background-position: -500px -500px; }
-.emoji-1F447-1F3FC { background-position: -520px 0px; }
+.emoji-1F447-1F3FC { background-position: -520px 0; }
.emoji-1F447-1F3FD { background-position: -520px -20px; }
.emoji-1F447-1F3FE { background-position: -520px -40px; }
.emoji-1F447-1F3FF { background-position: -520px -60px; }
@@ -700,7 +700,7 @@
.emoji-1F44B-1F3FB { background-position: -520px -460px; }
.emoji-1F44B-1F3FC { background-position: -520px -480px; }
.emoji-1F44B-1F3FD { background-position: -520px -500px; }
-.emoji-1F44B-1F3FE { background-position: 0px -520px; }
+.emoji-1F44B-1F3FE { background-position: 0 -520px; }
.emoji-1F44B-1F3FF { background-position: -20px -520px; }
.emoji-1F44C { background-position: -40px -520px; }
.emoji-1F44C-1F3FB { background-position: -60px -520px; }
@@ -727,7 +727,7 @@
.emoji-1F44F-1F3FE { background-position: -480px -520px; }
.emoji-1F44F-1F3FF { background-position: -500px -520px; }
.emoji-1F450 { background-position: -520px -520px; }
-.emoji-1F450-1F3FB { background-position: -540px 0px; }
+.emoji-1F450-1F3FB { background-position: -540px 0; }
.emoji-1F450-1F3FC { background-position: -540px -20px; }
.emoji-1F450-1F3FD { background-position: -540px -40px; }
.emoji-1F450-1F3FE { background-position: -540px -60px; }
@@ -754,7 +754,7 @@
.emoji-1F464 { background-position: -540px -480px; }
.emoji-1F465 { background-position: -540px -500px; }
.emoji-1F466 { background-position: -540px -520px; }
-.emoji-1F466-1F3FB { background-position: 0px -540px; }
+.emoji-1F466-1F3FB { background-position: 0 -540px; }
.emoji-1F466-1F3FC { background-position: -20px -540px; }
.emoji-1F466-1F3FD { background-position: -40px -540px; }
.emoji-1F466-1F3FE { background-position: -60px -540px; }
@@ -782,7 +782,7 @@
.emoji-1F468-1F469-1F467-1F467 { background-position: -500px -540px; }
.emoji-1F468-2764-1F468 { background-position: -520px -540px; }
.emoji-1F468-2764-1F48B-1F468 { background-position: -540px -540px; }
-.emoji-1F469 { background-position: -560px 0px; }
+.emoji-1F469 { background-position: -560px 0; }
.emoji-1F469-1F3FB { background-position: -560px -20px; }
.emoji-1F469-1F3FC { background-position: -560px -40px; }
.emoji-1F469-1F3FD { background-position: -560px -60px; }
@@ -810,7 +810,7 @@
.emoji-1F470-1F3FB { background-position: -560px -500px; }
.emoji-1F470-1F3FC { background-position: -560px -520px; }
.emoji-1F470-1F3FD { background-position: -560px -540px; }
-.emoji-1F470-1F3FE { background-position: 0px -560px; }
+.emoji-1F470-1F3FE { background-position: 0 -560px; }
.emoji-1F470-1F3FF { background-position: -20px -560px; }
.emoji-1F471 { background-position: -40px -560px; }
.emoji-1F471-1F3FB { background-position: -60px -560px; }
@@ -839,7 +839,7 @@
.emoji-1F475 { background-position: -520px -560px; }
.emoji-1F475-1F3FB { background-position: -540px -560px; }
.emoji-1F475-1F3FC { background-position: -560px -560px; }
-.emoji-1F475-1F3FD { background-position: -580px 0px; }
+.emoji-1F475-1F3FD { background-position: -580px 0; }
.emoji-1F475-1F3FE { background-position: -580px -20px; }
.emoji-1F475-1F3FF { background-position: -580px -40px; }
.emoji-1F476 { background-position: -580px -60px; }
@@ -868,7 +868,7 @@
.emoji-1F47C-1F3FC { background-position: -580px -520px; }
.emoji-1F47C-1F3FD { background-position: -580px -540px; }
.emoji-1F47C-1F3FE { background-position: -580px -560px; }
-.emoji-1F47C-1F3FF { background-position: 0px -580px; }
+.emoji-1F47C-1F3FF { background-position: 0 -580px; }
.emoji-1F47D { background-position: -20px -580px; }
.emoji-1F47E { background-position: -40px -580px; }
.emoji-1F47F { background-position: -60px -580px; }
@@ -898,7 +898,7 @@
.emoji-1F485-1F3FD { background-position: -540px -580px; }
.emoji-1F485-1F3FE { background-position: -560px -580px; }
.emoji-1F485-1F3FF { background-position: -580px -580px; }
-.emoji-1F486 { background-position: -600px 0px; }
+.emoji-1F486 { background-position: -600px 0; }
.emoji-1F486-1F3FB { background-position: -600px -20px; }
.emoji-1F486-1F3FC { background-position: -600px -40px; }
.emoji-1F486-1F3FD { background-position: -600px -60px; }
@@ -928,7 +928,7 @@
.emoji-1F497 { background-position: -600px -540px; }
.emoji-1F498 { background-position: -600px -560px; }
.emoji-1F499 { background-position: -600px -580px; }
-.emoji-1F49A { background-position: 0px -600px; }
+.emoji-1F49A { background-position: 0 -600px; }
.emoji-1F49B { background-position: -20px -600px; }
.emoji-1F49C { background-position: -40px -600px; }
.emoji-1F49D { background-position: -60px -600px; }
@@ -959,7 +959,7 @@
.emoji-1F4B1 { background-position: -560px -600px; }
.emoji-1F4B2 { background-position: -580px -600px; }
.emoji-1F4B3 { background-position: -600px -600px; }
-.emoji-1F4B4 { background-position: -620px 0px; }
+.emoji-1F4B4 { background-position: -620px 0; }
.emoji-1F4B5 { background-position: -620px -20px; }
.emoji-1F4B6 { background-position: -620px -40px; }
.emoji-1F4B7 { background-position: -620px -60px; }
@@ -990,7 +990,7 @@
.emoji-1F4D0 { background-position: -620px -560px; }
.emoji-1F4D1 { background-position: -620px -580px; }
.emoji-1F4D2 { background-position: -620px -600px; }
-.emoji-1F4D3 { background-position: 0px -620px; }
+.emoji-1F4D3 { background-position: 0 -620px; }
.emoji-1F4D4 { background-position: -20px -620px; }
.emoji-1F4D5 { background-position: -40px -620px; }
.emoji-1F4D6 { background-position: -60px -620px; }
@@ -1022,7 +1022,7 @@
.emoji-1F4F0 { background-position: -580px -620px; }
.emoji-1F4F1 { background-position: -600px -620px; }
.emoji-1F4F2 { background-position: -620px -620px; }
-.emoji-1F4F3 { background-position: -640px 0px; }
+.emoji-1F4F3 { background-position: -640px 0; }
.emoji-1F4F4 { background-position: -640px -20px; }
.emoji-1F4F5 { background-position: -640px -40px; }
.emoji-1F4F6 { background-position: -640px -60px; }
@@ -1054,7 +1054,7 @@
.emoji-1F510 { background-position: -640px -580px; }
.emoji-1F511 { background-position: -640px -600px; }
.emoji-1F512 { background-position: -640px -620px; }
-.emoji-1F513 { background-position: 0px -640px; }
+.emoji-1F513 { background-position: 0 -640px; }
.emoji-1F514 { background-position: -20px -640px; }
.emoji-1F515 { background-position: -40px -640px; }
.emoji-1F516 { background-position: -60px -640px; }
@@ -1087,7 +1087,7 @@
.emoji-1F531 { background-position: -600px -640px; }
.emoji-1F532 { background-position: -620px -640px; }
.emoji-1F533 { background-position: -640px -640px; }
-.emoji-1F534 { background-position: -660px 0px; }
+.emoji-1F534 { background-position: -660px 0; }
.emoji-1F535 { background-position: -660px -20px; }
.emoji-1F536 { background-position: -660px -40px; }
.emoji-1F537 { background-position: -660px -60px; }
@@ -1120,7 +1120,7 @@
.emoji-1F55B { background-position: -660px -600px; }
.emoji-1F55C { background-position: -660px -620px; }
.emoji-1F55D { background-position: -660px -640px; }
-.emoji-1F55E { background-position: 0px -660px; }
+.emoji-1F55E { background-position: 0 -660px; }
.emoji-1F55F { background-position: -20px -660px; }
.emoji-1F560 { background-position: -40px -660px; }
.emoji-1F561 { background-position: -60px -660px; }
@@ -1154,7 +1154,7 @@
.emoji-1F578 { background-position: -620px -660px; }
.emoji-1F579 { background-position: -640px -660px; }
.emoji-1F57B { background-position: -660px -660px; }
-.emoji-1F57E { background-position: -680px 0px; }
+.emoji-1F57E { background-position: -680px 0; }
.emoji-1F57F { background-position: -680px -20px; }
.emoji-1F581 { background-position: -680px -40px; }
.emoji-1F582 { background-position: -680px -60px; }
@@ -1188,7 +1188,7 @@
.emoji-1F595-1F3FF { background-position: -680px -620px; }
.emoji-1F596 { background-position: -680px -640px; }
.emoji-1F596-1F3FB { background-position: -680px -660px; }
-.emoji-1F596-1F3FC { background-position: 0px -680px; }
+.emoji-1F596-1F3FC { background-position: 0 -680px; }
.emoji-1F596-1F3FD { background-position: -20px -680px; }
.emoji-1F596-1F3FE { background-position: -40px -680px; }
.emoji-1F596-1F3FF { background-position: -60px -680px; }
@@ -1223,7 +1223,7 @@
.emoji-1F5C4 { background-position: -640px -680px; }
.emoji-1F5C6 { background-position: -660px -680px; }
.emoji-1F5C7 { background-position: -680px -680px; }
-.emoji-1F5C9 { background-position: -700px 0px; }
+.emoji-1F5C9 { background-position: -700px 0; }
.emoji-1F5CA { background-position: -700px -20px; }
.emoji-1F5CE { background-position: -700px -40px; }
.emoji-1F5CF { background-position: -700px -60px; }
@@ -1258,7 +1258,7 @@
.emoji-1F5F8 { background-position: -700px -640px; }
.emoji-1F5F9 { background-position: -700px -660px; }
.emoji-1F5FA { background-position: -700px -680px; }
-.emoji-1F5FB { background-position: 0px -700px; }
+.emoji-1F5FB { background-position: 0 -700px; }
.emoji-1F5FC { background-position: -20px -700px; }
.emoji-1F5FD { background-position: -40px -700px; }
.emoji-1F5FE { background-position: -60px -700px; }
@@ -1294,7 +1294,7 @@
.emoji-1F61C { background-position: -660px -700px; }
.emoji-1F61D { background-position: -680px -700px; }
.emoji-1F61E { background-position: -700px -700px; }
-.emoji-1F61F { background-position: -720px 0px; }
+.emoji-1F61F { background-position: -720px 0; }
.emoji-1F620 { background-position: -720px -20px; }
.emoji-1F621 { background-position: -720px -40px; }
.emoji-1F622 { background-position: -720px -60px; }
@@ -1330,7 +1330,7 @@
.emoji-1F640 { background-position: -720px -660px; }
.emoji-1F641 { background-position: -720px -680px; }
.emoji-1F642 { background-position: -720px -700px; }
-.emoji-1F643 { background-position: 0px -720px; }
+.emoji-1F643 { background-position: 0 -720px; }
.emoji-1F644 { background-position: -20px -720px; }
.emoji-1F645 { background-position: -40px -720px; }
.emoji-1F645-1F3FB { background-position: -60px -720px; }
@@ -1367,7 +1367,7 @@
.emoji-1F64C-1F3FF { background-position: -680px -720px; }
.emoji-1F64D { background-position: -700px -720px; }
.emoji-1F64D-1F3FB { background-position: -720px -720px; }
-.emoji-1F64D-1F3FC { background-position: -740px 0px; }
+.emoji-1F64D-1F3FC { background-position: -740px 0; }
.emoji-1F64D-1F3FD { background-position: -740px -20px; }
.emoji-1F64D-1F3FE { background-position: -740px -40px; }
.emoji-1F64D-1F3FF { background-position: -740px -60px; }
@@ -1404,7 +1404,7 @@
.emoji-1F692 { background-position: -740px -680px; }
.emoji-1F693 { background-position: -740px -700px; }
.emoji-1F694 { background-position: -740px -720px; }
-.emoji-1F695 { background-position: 0px -740px; }
+.emoji-1F695 { background-position: 0 -740px; }
.emoji-1F696 { background-position: -20px -740px; }
.emoji-1F697 { background-position: -40px -740px; }
.emoji-1F698 { background-position: -60px -740px; }
@@ -1442,7 +1442,7 @@
.emoji-1F6B3 { background-position: -700px -740px; }
.emoji-1F6B4 { background-position: -720px -740px; }
.emoji-1F6B4-1F3FB { background-position: -740px -740px; }
-.emoji-1F6B4-1F3FC { background-position: -760px 0px; }
+.emoji-1F6B4-1F3FC { background-position: -760px 0; }
.emoji-1F6B4-1F3FD { background-position: -760px -20px; }
.emoji-1F6B4-1F3FE { background-position: -760px -40px; }
.emoji-1F6B4-1F3FF { background-position: -760px -60px; }
@@ -1480,7 +1480,7 @@
.emoji-1F6C5 { background-position: -760px -700px; }
.emoji-1F6C6 { background-position: -760px -720px; }
.emoji-1F6C7 { background-position: -760px -740px; }
-.emoji-1F6C8 { background-position: 0px -760px; }
+.emoji-1F6C8 { background-position: 0 -760px; }
.emoji-1F6C9 { background-position: -20px -760px; }
.emoji-1F6CA { background-position: -40px -760px; }
.emoji-1F6CB { background-position: -60px -760px; }
@@ -1519,7 +1519,7 @@
.emoji-1F918-1F3FC { background-position: -720px -760px; }
.emoji-1F918-1F3FD { background-position: -740px -760px; }
.emoji-1F918-1F3FE { background-position: -760px -760px; }
-.emoji-1F918-1F3FF { background-position: -780px 0px; }
+.emoji-1F918-1F3FF { background-position: -780px 0; }
.emoji-1F980 { background-position: -780px -20px; }
.emoji-1F981 { background-position: -780px -40px; }
.emoji-1F982 { background-position: -780px -60px; }
@@ -1558,7 +1558,7 @@
.emoji-24C2 { background-position: -780px -720px; }
.emoji-25AA { background-position: -780px -740px; }
.emoji-25AB { background-position: -780px -760px; }
-.emoji-25B6 { background-position: 0px -780px; }
+.emoji-25B6 { background-position: 0 -780px; }
.emoji-25C0 { background-position: -20px -780px; }
.emoji-25FB { background-position: -40px -780px; }
.emoji-25FC { background-position: -60px -780px; }
@@ -1598,7 +1598,7 @@
.emoji-264D { background-position: -740px -780px; }
.emoji-264E { background-position: -760px -780px; }
.emoji-264F { background-position: -780px -780px; }
-.emoji-2650 { background-position: -800px 0px; }
+.emoji-2650 { background-position: -800px 0; }
.emoji-2651 { background-position: -800px -20px; }
.emoji-2652 { background-position: -800px -40px; }
.emoji-2653 { background-position: -800px -60px; }
@@ -1638,7 +1638,7 @@
.emoji-26F0 { background-position: -800px -740px; }
.emoji-26F1 { background-position: -800px -760px; }
.emoji-26F2 { background-position: -800px -780px; }
-.emoji-26F3 { background-position: 0px -800px; }
+.emoji-26F3 { background-position: 0 -800px; }
.emoji-26F4 { background-position: -20px -800px; }
.emoji-26F5 { background-position: -40px -800px; }
.emoji-26F7 { background-position: -60px -800px; }
@@ -1679,7 +1679,7 @@
.emoji-270D-1F3FD { background-position: -760px -800px; }
.emoji-270D-1F3FE { background-position: -780px -800px; }
.emoji-270D-1F3FF { background-position: -800px -800px; }
-.emoji-270F { background-position: -820px 0px; }
+.emoji-270F { background-position: -820px 0; }
.emoji-2712 { background-position: -820px -20px; }
.emoji-2714 { background-position: -820px -40px; }
.emoji-2716 { background-position: -820px -60px; }
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index 35df9a61c86..84eefd01cfe 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -6,7 +6,7 @@
font-size: $gl-font-size;
padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top);
border-bottom: 1px solid $table-border-color;
- color: #7f8fa4;
+ color: $list-text-color;
&.event-inline {
.avatar {
@@ -21,7 +21,7 @@
}
a {
- color: #4c4e54;
+ color: $gl-dark-link-color;
}
.avatar {
@@ -31,10 +31,7 @@
.event-title {
@include str-truncated(calc(100% - 174px));
font-weight: 600;
-
- .author_name {
- color: #333;
- }
+ color: $list-text-color;
}
.event-body {
@@ -63,7 +60,7 @@
.note-image-attach {
margin-top: 4px;
- margin-left: 0px;
+ margin-left: 0;
max-width: 200px;
float: none;
}
@@ -83,10 +80,10 @@
.event_icon {
position: relative;
float: right;
- border: 1px solid #EEE;
+ border: 1px solid #eee;
padding: 5px;
@include border-radius(5px);
- background: #F9F9F9;
+ background: #f9f9f9;
margin-left: 10px;
top: -6px;
img {
@@ -94,7 +91,7 @@
}
}
- &:last-child { border:none }
+ &:last-child { border: none }
.event_commits {
li {
@@ -138,7 +135,7 @@
@include str-truncated(100%);
padding: 5px 0;
font-size: 13px;
- float:left;
+ float: left;
margin-right: -150px;
padding-right: 150px;
line-height: 20px;
@@ -160,7 +157,7 @@
.event-body {
margin: 0;
- border-left: 2px solid #DDD;
+ border-left: 2px solid #ddd;
padding-left: 10px;
}
diff --git a/app/assets/stylesheets/pages/graph.scss b/app/assets/stylesheets/pages/graph.scss
index c3b10d144e1..4e5c4ed84b6 100644
--- a/app/assets/stylesheets/pages/graph.scss
+++ b/app/assets/stylesheets/pages/graph.scss
@@ -6,11 +6,11 @@
font-size: 14px;
padding: 5px;
border-bottom: 1px solid $border-color;
- background: #EEE;
+ background: #eee;
}
.network-graph {
- background: #FFF;
+ background: #fff;
height: 500px;
overflow-y: scroll;
overflow-x: hidden;
diff --git a/app/assets/stylesheets/pages/import.scss b/app/assets/stylesheets/pages/import.scss
index 3df4bb84bd2..6a99cd9cb94 100644
--- a/app/assets/stylesheets/pages/import.scss
+++ b/app/assets/stylesheets/pages/import.scss
@@ -1,6 +1,6 @@
i.icon-gitorious {
display: inline-block;
- background-position: 0px 0px;
+ background-position: 0 0;
background-size: contain;
background-repeat: no-repeat;
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 1310e6ad7c7..2760af8a48a 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -1,34 +1,3 @@
-@media (max-width: $screen-sm-max) {
- .issuable-affix {
- margin-top: 20px;
- }
-}
-
-@media (max-width: $screen-md-max) {
- .issuable-affix {
- position: static;
- }
-}
-
-@media (min-width: $screen-md-max) {
- .issuable-affix {
- &.affix-top {
- position: static;
- }
-
- &.affix {
- position: fixed;
- top: 70px;
- margin-right: 35px;
-
- &.no-affix {
- position: relative;
- top: 0;
- }
- }
- }
-}
-
.issuable-details {
section {
.issuable-discussion {
@@ -54,20 +23,25 @@
padding: 6px 10px;
}
}
+
+ &.has-labels {
+ margin-bottom: -5px;
+ }
}
.issuable-sidebar {
.block {
@include clearfix;
- padding: $gl-padding 0;
+ padding: $gl-padding 0;
border-bottom: 1px solid $border-gray-light;
// This prevents the mess when resizing the sidebar
// of elements repositioning themselves..
width: $gutter_inner_width;
// --
- &:first-child {
- padding-top: 5px;
+ &.issuable-sidebar-header {
+ padding-top: 0;
+ padding-bottom: 10px;
}
&:last-child {
@@ -75,7 +49,6 @@
}
span {
- margin-top: 7px;
display: inline-block;
}
@@ -84,7 +57,7 @@
}
.issuable-count {
-
+ margin-top: 7px;
}
.gutter-toggle {
@@ -99,19 +72,19 @@
.title {
color: $gl-text-color;
- margin-bottom: 8px;
+ margin-bottom: 10px;
+ line-height: 1;
.avatar {
margin-left: 0;
}
- label {
- font-weight: normal;
- margin-right: 4px;
- }
-
.edit-link {
color: $gl-gray;
+
+ &:hover {
+ color: $md-link-color;
+ }
}
}
@@ -144,11 +117,6 @@
.btn-clipboard {
color: $gl-gray;
}
-
- .participants .avatar {
- margin-top: 6px;
- margin-right: 2px;
- }
}
.right-sidebar {
@@ -163,8 +131,12 @@
&.right-sidebar-expanded {
width: $gutter_width;
- hr {
- display: none;
+ .value {
+ line-height: 1;
+ }
+
+ .bold {
+ font-weight: 600;
}
.sidebar-collapsed-icon {
@@ -172,8 +144,23 @@
}
.gutter-toggle {
+ margin-top: 7px;
border-left: 1px solid $border-gray-light;
}
+
+ .assignee .avatar {
+ float: left;
+ margin-right: 10px;
+ margin-bottom: 0;
+ margin-left: 0;
+ }
+
+ .username {
+ display: block;
+ margin-top: 4px;
+ font-size: 13px;
+ font-weight: normal;
+ }
}
.subscribe-button {
@@ -193,14 +180,6 @@
width: $sidebar_collapsed_width;
padding-top: 0;
- hr {
- margin: 0;
- color: $gray-normal;
- border-color: $gray-normal;
- width: 62px;
- margin-left: -20px
- }
-
.block {
width: $sidebar_collapsed_width - 1px;
margin-left: -19px;
@@ -209,12 +188,18 @@
overflow: hidden;
}
+ .participants {
+ border-bottom: 1px solid $border-gray-light;
+ }
+
.hide-collapsed {
display: none;
}
.gutter-toggle {
- margin-left: -36px;
+ width: 100%;
+ margin-left: 0;
+ padding-left: 25px;
}
.sidebar-collapsed-icon {
@@ -222,13 +207,17 @@
width: 100%;
text-align: center;
padding-bottom: 10px;
- color: #999999;
+ color: #999;
span {
display: block;
margin-top: 0;
}
+ .author {
+ display: none;
+ }
+
.btn-clipboard {
border: none;
@@ -237,10 +226,15 @@
}
i {
- color: #999999;
+ color: #999;
}
}
}
+
+ .sidebar-collapsed-user {
+ padding-bottom: 0;
+ margin-bottom: 10px;
+ }
}
.btn {
@@ -251,6 +245,13 @@
border: 1px solid $border-gray-dark;
}
}
+
+ a:not(.btn) {
+ &:hover {
+ color: $md-link-color;
+ text-decoration: none;
+ }
+ }
}
.btn-default.gutter-toggle {
@@ -262,3 +263,37 @@
color: $gray-darkest;
}
}
+
+.edited-text {
+ color: $gray-darkest;
+
+ .author_link {
+ color: $gray-darkest;
+ }
+}
+
+.participants-list {
+ margin: -5px -5px;
+}
+
+.participants-author {
+ display: inline-block;
+ padding: 5px 5px;
+
+ .author_link {
+ display: block;
+ }
+
+ .avatar.avatar-inline {
+ margin: 0;
+ }
+}
+
+.participants-more {
+ margin-top: 5px;
+ margin-left: 5px;
+
+ a {
+ color: #8c8c8c;
+ }
+}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 1b686c58eaf..6a1d28590c2 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -3,7 +3,7 @@
padding: 10px $gl-padding;
position: relative;
- .issue-title {
+ .title {
margin-bottom: 2px;
}
@@ -49,7 +49,7 @@ form.edit-issue {
margin: 0;
}
-.merge-requests-title {
+.merge-requests-title, .related-branches-title {
font-size: 16px;
font-weight: 600;
}
@@ -68,18 +68,18 @@ form.edit-issue {
.merge-request,
.issue {
&.today {
- background: #EFE;
- border-color: #CEC;
+ background: #efe;
+ border-color: #cec;
}
&.closed {
- background: #F9F9F9;
- border-color: #E5E5E5;
+ background: #f9f9f9;
+ border-color: #e5e5e5;
}
&.merged {
- background: #F9F9F9;
- border-color: #E5E5E5;
+ background: #f9f9f9;
+ border-color: #e5e5e5;
}
}
@@ -130,14 +130,14 @@ form.edit-issue {
}
.issue-closed-by-widget {
- color: $secondary-text;
+ color: $gl-text-color;
margin-left: 52px;
}
.editor-details {
display: block;
-
+
@media (min-width: $screen-sm-min) {
display: inline-block;
}
-} \ No newline at end of file
+}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 61bec02f6c5..bc41f7d306f 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -28,7 +28,7 @@
img {
max-width: 100%;
- margin-bottom: 30px;
+ margin-bottom: 30px;
}
a {
@@ -39,7 +39,7 @@
.login-box{
background: #fafafa;
border-radius: 10px;
- box-shadow: 0 0px 2px #CCC;
+ box-shadow: 0 0 2px #ccc;
padding: 15px;
.login-heading h3 {
@@ -74,7 +74,7 @@
&.top {
@include border-radius(5px 5px 0 0);
- margin-bottom: 0px;
+ margin-bottom: 0;
}
&.bottom {
@@ -85,12 +85,12 @@
&.middle {
border-top: 0;
- margin-bottom:0px;
+ margin-bottom: 0;
@include border-radius(0);
}
&:active, &:focus {
- background-color: #FFF;
+ background-color: #fff;
}
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 2772623f4bd..cee5c47cfb2 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -113,7 +113,7 @@
}
.mr-widget-footer {
- border-top: 1px solid #EEE;
+ border-top: 1px solid #eee;
}
.ci-coverage {
@@ -222,7 +222,7 @@
margin-bottom: 20px;
span {
- color: #B2B2B2;
+ color: #b2b2b2;
a {
color: $md-link-color;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 158c2a47862..61783ec46aa 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -156,7 +156,7 @@
.comment-hints {
color: #999;
- background: #FFF;
+ background: #fff;
padding: 7px;
margin-top: -7px;
border: 1px solid $border-color;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index d5f9852ebed..d408853cc80 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -3,16 +3,16 @@
*/
@-webkit-keyframes targe3-note {
- from { background:#fffff0; }
- 50% { background:#ffffd3; }
- to { background:#fffff0; }
+ from { background: #fffff0; }
+ 50% { background: #ffffd3; }
+ to { background: #fffff0; }
}
ul.notes {
display: block;
list-style: none;
- margin: 0px;
- padding: 0px;
+ margin: 0;
+ padding: 0;
.timeline-icon {
float: left;
@@ -30,7 +30,7 @@ ul.notes {
font-size: 14px;
padding-top: 10px;
padding-bottom: 10px;
- background: #FDFDFD;
+ background: #fdfdfd;
.timeline-icon {
.avatar {
@@ -93,12 +93,12 @@ ul.notes {
.discussion {
overflow: hidden;
display: block;
- position:relative;
+ position: relative;
}
.note {
display: block;
- position:relative;
+ position: relative;
.note-body {
overflow: auto;
@@ -108,6 +108,13 @@ ul.notes {
word-wrap: break-word;
@include md-typography;
+ // On diffs code should wrap nicely and not overflow
+ pre {
+ code {
+ white-space: pre-wrap;
+ }
+ }
+
// Reset ul style types since we're nested inside a ul already
& > ul {
list-style-type: disc;
@@ -129,7 +136,7 @@ ul.notes {
hr {
// Darken 'whitesmoke' a bit to make it more visible in note bodies
- border-color: darken(#F5F5F5, 8%);
+ border-color: darken(#f5f5f5, 8%);
margin: 10px 0;
}
}
@@ -166,7 +173,7 @@ ul.notes {
vertical-align: middle;
text-align: center;
padding: 10px 0;
- background: #FFF;
+ background: #fff;
color: $text-color;
}
&.notes_line2 {
@@ -232,7 +239,7 @@ ul.notes {
.add-diff-note {
margin-top: -4px;
@include border-radius(40px);
- background: #FFF;
+ background: #fff;
padding: 4px;
font-size: 16px;
color: $gl-link-color;
@@ -249,7 +256,7 @@ ul.notes {
&:hover {
background: $gl-info;
- color: #FFF;
+ color: #fff;
@include show-add-diff-note;
}
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index ecfe0e37c85..260179074cf 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -30,7 +30,7 @@
.btn {
line-height: 40px;
height: 42px;
- padding: 0px 12px;
+ padding: 0 12px;
img {
width: 32px;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 1a7b0c1e278..250de079ff5 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -33,6 +33,13 @@
.project-settings-dropdown {
margin-left: 10px;
display: inline-block;
+
+ .dropdown-menu {
+ left: auto;
+ width: auto;
+ right: 0px;
+ max-width: 240px;
+ }
}
}
@@ -63,7 +70,7 @@
.project-repo-buttons {
margin-top: 20px;
- margin-bottom: 0px;
+ margin-bottom: 0;
.count-buttons {
display: block;
@@ -118,7 +125,7 @@
left: 1px;
margin-top: -9px;
border-width: 10px 7px 10px 0;
- border-right-color: #FFF;
+ border-right-color: #fff;
}
}
.count {
@@ -140,10 +147,10 @@
cursor: pointer;
background-image: none;
white-space: nowrap;
- margin: 0 11px 0px 4px;
+ margin: 0 11px 0 4px;
&:hover {
- background: #FFF;
+ background: #fff;
}
}
}
@@ -188,7 +195,7 @@
}
.project_member_row form {
- margin: 0px;
+ margin: 0;
}
.transfer-project .select2-container {
@@ -264,11 +271,11 @@ table.table.protected-branches-list tr.no-border {
padding-bottom: 4px;
ul.nav {
- display:inline-block;
+ display: inline-block;
}
.nav li {
- display:inline;
+ display: inline;
}
.nav > li > a {
@@ -281,11 +288,11 @@ table.table.protected-branches-list tr.no-border {
}
li {
- display:inline;
+ display: inline;
}
a {
- float:left;
+ float: left;
font-size: 17px;
}
@@ -440,7 +447,7 @@ pre.light-well {
.form-control {
@extend .monospace;
- background: #FFF;
+ background: #fff;
font-size: 14px;
margin-left: -1px;
cursor: auto;
@@ -450,16 +457,16 @@ pre.light-well {
.cannot-be-merged,
.cannot-be-merged:hover {
- color: #E62958;
+ color: #e62958;
margin-top: 2px;
}
.private-forks-notice .private-fork-icon {
i:nth-child(1) {
- color: #2AA056;
+ color: #2aa056;
}
i:nth-child(2) {
- color: #FFFFFF;
+ color: #fff;
}
}
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index a9111a7388f..eec22c5dc96 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -1,7 +1,7 @@
.runner-state {
padding: 6px 12px;
margin-right: 10px;
- color: #FFF;
+ color: #fff;
&.runner-state-shared {
background: #32b186;
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 84234b15c65..b6e45024644 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -16,7 +16,7 @@
margin-bottom: 20px;
input {
- border-color: #BBB;
+ border-color: #bbb;
font-weight: bold;
}
}
diff --git a/app/assets/stylesheets/pages/sherlock.scss b/app/assets/stylesheets/pages/sherlock.scss
index 92d84d9640f..bed6470dbd3 100644
--- a/app/assets/stylesheets/pages/sherlock.scss
+++ b/app/assets/stylesheets/pages/sherlock.scss
@@ -13,13 +13,13 @@ table .sherlock-code {
}
.sherlock-line-samples-table {
- margin-bottom: 0px !important;
+ margin-bottom: 0 !important;
thead tr th,
tbody tr td {
font-size: 13px !important;
text-align: right;
- padding: 0px 10px !important;
+ padding: 0 10px !important;
}
}
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 4b6ef035673..6f777d11641 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -1,7 +1,7 @@
.ci-status {
padding: 2px 7px;
margin-right: 5px;
- border: 1px solid #EEE;
+ border: 1px solid #eee;
white-space: nowrap;
@include border-radius(4px);
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 479c3c16d46..f983e9829e6 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -14,25 +14,8 @@
}
.todo-item {
- font-size: $gl-font-size;
- padding-left: $gl-avatar-size + $gl-padding-top;
- color: $secondary-text;
-
- a {
- color: #4c4e54;
- }
-
- .avatar {
- margin-left: -($gl-avatar-size + $gl-padding-top);
- }
-
.todo-title {
@include str-truncated(calc(100% - 174px));
- font-weight: 600;
-
- .author-name {
- color: #333;
- }
}
.todo-body {
@@ -61,7 +44,7 @@
.note-image-attach {
margin-top: 4px;
- margin-left: 0px;
+ margin-left: 0;
max-width: 200px;
float: none;
}
@@ -89,7 +72,7 @@
.todo-body {
margin: 0;
- border-left: 2px solid #DDD;
+ border-left: 2px solid #ddd;
padding-left: 10px;
}
}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index ef63b010600..25b5e95583e 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -41,12 +41,12 @@
vertical-align: middle;
i, a {
- color: $gl-link-color;
+ color: $gl-dark-link-color;
}
img {
position: relative;
- top:-1px;
+ top: -1px;
}
}
diff --git a/app/assets/stylesheets/pages/ui_dev_kit.scss b/app/assets/stylesheets/pages/ui_dev_kit.scss
index 05fa9312efb..587bd6a1e8a 100644
--- a/app/assets/stylesheets/pages/ui_dev_kit.scss
+++ b/app/assets/stylesheets/pages/ui_dev_kit.scss
@@ -7,7 +7,7 @@
.example {
&:before {
content: "Example";
- color: #BBB;
+ color: #bbb;
}
padding: 15px;
diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
index 9a50096c0d0..8886c1dff56 100644
--- a/app/assets/stylesheets/pages/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -2,23 +2,23 @@
// color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg
// see also: https://gist.github.com/jasonm23/2868981
- $black: #000000;
+ $black: #000;
$red: #cd0000;
$green: #00cd00;
$yellow: #cdcd00;
- $blue: #0000ee; // according to wikipedia, this is the xterm standard
+ $blue: #00e; // according to wikipedia, this is the xterm standard
//$blue: #1e90ff; // this is used by all the terminals I tried (when configured with the xterm color profile)
$magenta: #cd00cd;
$cyan: #00cdcd;
$white: #e5e5e5;
$l-black: #7f7f7f;
- $l-red: #ff0000;
- $l-green: #00ff00;
- $l-yellow: #ffff00;
+ $l-red: #f00;
+ $l-green: #0f0;
+ $l-yellow: #ff0;
$l-blue: #5c5cff;
- $l-magenta: #ff00ff;
- $l-cyan: #00ffff;
- $l-white: #ffffff;
+ $l-magenta: #f0f;
+ $l-cyan: #0ff;
+ $l-white: #fff;
.term-bold {
font-weight: bold;
@@ -136,7 +136,7 @@
.xterm-fg-0 {
- color: #000000;
+ color: #000;
}
.xterm-fg-1 {
color: #800000;
@@ -163,28 +163,28 @@
color: #808080;
}
.xterm-fg-9 {
- color: #ff0000;
+ color: #f00;
}
.xterm-fg-10 {
- color: #00ff00;
+ color: #0f0;
}
.xterm-fg-11 {
- color: #ffff00;
+ color: #ff0;
}
.xterm-fg-12 {
- color: #0000ff;
+ color: #00f;
}
.xterm-fg-13 {
- color: #ff00ff;
+ color: #f0f;
}
.xterm-fg-14 {
- color: #00ffff;
+ color: #0ff;
}
.xterm-fg-15 {
- color: #ffffff;
+ color: #fff;
}
.xterm-fg-16 {
- color: #000000;
+ color: #000;
}
.xterm-fg-17 {
color: #00005f;
@@ -199,7 +199,7 @@
color: #0000d7;
}
.xterm-fg-21 {
- color: #0000ff;
+ color: #00f;
}
.xterm-fg-22 {
color: #005f00;
@@ -274,7 +274,7 @@
color: #00d7ff;
}
.xterm-fg-46 {
- color: #00ff00;
+ color: #0f0;
}
.xterm-fg-47 {
color: #00ff5f;
@@ -289,7 +289,7 @@
color: #00ffd7;
}
.xterm-fg-51 {
- color: #00ffff;
+ color: #0ff;
}
.xterm-fg-52 {
color: #5f0000;
@@ -724,7 +724,7 @@
color: #d7ffff;
}
.xterm-fg-196 {
- color: #ff0000;
+ color: #f00;
}
.xterm-fg-197 {
color: #ff005f;
@@ -739,7 +739,7 @@
color: #ff00d7;
}
.xterm-fg-201 {
- color: #ff00ff;
+ color: #f0f;
}
.xterm-fg-202 {
color: #ff5f00;
@@ -814,7 +814,7 @@
color: #ffd7ff;
}
.xterm-fg-226 {
- color: #ffff00;
+ color: #ff0;
}
.xterm-fg-227 {
color: #ffff5f;
@@ -829,7 +829,7 @@
color: #ffffd7;
}
.xterm-fg-231 {
- color: #ffffff;
+ color: #fff;
}
.xterm-fg-232 {
color: #080808;
@@ -850,7 +850,7 @@
color: #3a3a3a;
}
.xterm-fg-238 {
- color: #444444;
+ color: #444;
}
.xterm-fg-239 {
color: #4e4e4e;
@@ -901,6 +901,6 @@
color: #e4e4e4;
}
.xterm-fg-255 {
- color: #eeeeee;
+ color: #eee;
}
}
diff --git a/app/controllers/admin/abuse_reports_controller.rb b/app/controllers/admin/abuse_reports_controller.rb
index 2463cfa87be..e9b0972bdd8 100644
--- a/app/controllers/admin/abuse_reports_controller.rb
+++ b/app/controllers/admin/abuse_reports_controller.rb
@@ -6,7 +6,7 @@ class Admin::AbuseReportsController < Admin::ApplicationController
def destroy
abuse_report = AbuseReport.find(params[:id])
- abuse_report.remove_user if params[:remove_user]
+ abuse_report.remove_user(deleted_by: current_user) if params[:remove_user]
abuse_report.destroy
render nothing: true
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index be192964a93..9abf08d0e19 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -119,10 +119,10 @@ class Admin::UsersController < Admin::ApplicationController
end
def destroy
- DeleteUserService.new(current_user).execute(user)
+ DeleteUserWorker.perform_async(current_user.id, user.id)
respond_to do |format|
- format.html { redirect_to admin_users_path }
+ format.html { redirect_to admin_users_path, notice: "The user is being deleted." }
format.json { head :ok }
end
end
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index 43cf8fa71af..be488483b09 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -1,25 +1,34 @@
class Dashboard::TodosController < Dashboard::ApplicationController
- before_action :find_todos, only: [:index, :destroy_all]
+ before_action :find_todos, only: [:index, :destroy, :destroy_all]
def index
@todos = @todos.page(params[:page]).per(PER_PAGE)
end
def destroy
- todo.done!
+ todo.done
+
+ todo_notice = 'Todo was successfully marked as done.'
respond_to do |format|
- format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' }
+ format.html { redirect_to dashboard_todos_path, notice: todo_notice }
format.js { render nothing: true }
+ format.json do
+ render json: { count: @todos.size, done_count: current_user.todos.done.count }
+ end
end
end
def destroy_all
- @todos.each(&:done!)
+ @todos.each(&:done)
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
format.js { render nothing: true }
+ format.json do
+ find_todos
+ render json: { count: @todos.size, done_count: current_user.todos.done.count }
+ end
end
end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 139e40db180..b538c7d1608 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -3,7 +3,7 @@ class DashboardController < Dashboard::ApplicationController
include MergeRequestsAction
before_action :event_filter, only: :activity
- before_action :projects, only: [:issues, :merge_requests]
+ before_action :projects, only: [:issues, :merge_requests, :labels, :milestones]
respond_to :html
@@ -20,6 +20,29 @@ class DashboardController < Dashboard::ApplicationController
end
end
+ def labels
+ labels = Label.where(project_id: @projects).select(:title, :color).uniq(:title)
+
+ respond_to do |format|
+ format.json do
+ render json: labels
+ end
+ end
+ end
+
+ def milestones
+ milestones = Milestone.where(project_id: @projects).active
+ epoch = DateTime.parse('1970-01-01')
+ grouped_milestones = GlobalMilestone.build_collection(milestones)
+ grouped_milestones = grouped_milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date }
+
+ respond_to do |format|
+ format.json do
+ render json: grouped_milestones
+ end
+ end
+ end
+
protected
def load_events
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index 24025d8c723..c721dca58d9 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -7,6 +7,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
if pre_auth.authorizable?
if skip_authorization? || matching_token?
auth = authorization.authorize
+ session.delete(:user_return_to)
redirect_to auth.redirect_uri
else
render "doorkeeper/authorizations/new"
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index dc9c96df003..6ff47c4033a 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -1,5 +1,5 @@
class Projects::BadgesController < Projects::ApplicationController
- before_action :set_no_cache
+ before_action :no_cache_headers
def build
respond_to do |format|
@@ -10,15 +10,4 @@ class Projects::BadgesController < Projects::ApplicationController
end
end
end
-
- private
-
- def set_no_cache
- expires_now
-
- # Add some deprecated headers for older agents
- #
- response.headers['Pragma'] = 'no-cache'
- response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
- end
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 4db3b3bf23d..43ea717cbd2 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -9,7 +9,7 @@ class Projects::BranchesController < Projects::ApplicationController
@sort = params[:sort] || 'name'
@branches = @repository.branches_sorted_by(@sort)
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE)
-
+
@max_commits = @branches.reduce(0) do |memo, branch|
diverging_commit_counts = repository.diverging_commit_counts(branch)
[memo, diverging_commit_counts[:behind], diverging_commit_counts[:ahead]].max
@@ -23,11 +23,15 @@ class Projects::BranchesController < Projects::ApplicationController
def create
branch_name = sanitize(strip_tags(params[:branch_name]))
branch_name = Addressable::URI.unescape(branch_name)
- ref = sanitize(strip_tags(params[:ref]))
- ref = Addressable::URI.unescape(ref)
+
result = CreateBranchService.new(project, current_user).
execute(branch_name, ref)
+ if params[:issue_iid]
+ issue = @project.issues.find_by(iid: params[:issue_iid])
+ SystemNoteService.new_issue_branch(issue, @project, current_user, branch_name) if issue
+ end
+
if result[:status] == :success
@branch = result[:branch]
redirect_to namespace_project_tree_path(@project.namespace, @project,
@@ -49,4 +53,15 @@ class Projects::BranchesController < Projects::ApplicationController
format.js { render status: status[:return_code] }
end
end
+
+ private
+
+ def ref
+ if params[:ref]
+ ref_escaped = sanitize(strip_tags(params[:ref]))
+ Addressable::URI.unescape(ref_escaped)
+ else
+ @project.default_branch
+ end
+ end
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index b0a03ee45cc..6603f28a082 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -5,7 +5,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :issue, only: [:edit, :update, :show]
# Allow read any issue
- before_action :authorize_read_issue!
+ before_action :authorize_read_issue!, only: [:show]
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
@@ -65,6 +65,7 @@ class Projects::IssuesController < Projects::ApplicationController
@notes = @issue.notes.nonawards.with_associations.fresh
@noteable = @issue
@merge_requests = @issue.referenced_merge_requests(current_user)
+ @related_branches = @issue.related_branches - @merge_requests.map(&:source_branch)
respond_with(@issue)
end
@@ -127,6 +128,10 @@ class Projects::IssuesController < Projects::ApplicationController
end
alias_method :subscribable_resource, :issue
+ def authorize_read_issue!
+ return render_404 unless can?(current_user, :read_issue, @issue)
+ end
+
def authorize_update_issue!
return render_404 unless can?(current_user, :update_issue, @issue)
end
@@ -157,7 +162,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue_params
params.require(:issue).permit(
- :title, :assignee_id, :position, :description,
+ :title, :assignee_id, :position, :description, :confidential,
:milestone_id, :state_event, :task_num, label_ids: []
)
end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 40d8098690a..5f471d405f5 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -12,6 +12,13 @@ class Projects::LabelsController < Projects::ApplicationController
def index
@labels = @project.labels.page(params[:page]).per(PER_PAGE)
+
+ respond_to do |format|
+ format.html
+ format.json do
+ render json: @project.labels
+ end
+ end
end
def new
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 61b82c9db46..7248ede1699 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -5,7 +5,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled
before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
- :ci_status, :cancel_merge_when_build_succeeds
+ :ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip
]
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
@@ -20,7 +20,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :authorize_create_merge_request!, only: [:new, :create]
# Allow modify merge_request
- before_action :authorize_update_merge_request!, only: [:close, :edit, :update, :sort]
+ before_action :authorize_update_merge_request!, only: [:close, :edit, :update, :remove_wip, :sort]
def index
terms = params['issue_search']
@@ -164,6 +164,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
+ def remove_wip
+ MergeRequests::UpdateService.new(project, current_user, title: @merge_request.wipless_title).execute(@merge_request)
+
+ redirect_to namespace_project_merge_request_path(@project.namespace, @project, @merge_request),
+ notice: "The merge request can now be merged."
+ end
+
def merge_check
@merge_request.check_if_can_be_merged
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index da46731d945..0998b191c07 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -19,7 +19,15 @@ class Projects::MilestonesController < Projects::ApplicationController
end
@milestones = @milestones.includes(:project)
- @milestones = @milestones.page(params[:page]).per(PER_PAGE)
+
+ respond_to do |format|
+ format.html do
+ @milestones = @milestones.page(params[:page]).per(PER_PAGE)
+ end
+ format.json do
+ render json: @milestones
+ end
+ end
end
def new
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 36f37221c58..c9930480770 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -134,7 +134,7 @@ class ProjectsController < ApplicationController
def autocomplete_sources
note_type = params['type']
note_id = params['type_id']
- autocomplete = ::Projects::AutocompleteService.new(@project)
+ autocomplete = ::Projects::AutocompleteService.new(@project, current_user)
participants = ::Projects::ParticipantsService.new(@project, current_user).execute(note_type, note_id)
@suggestions = {
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 20a2b0ce8f0..c2befa5a5b3 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -19,4 +19,10 @@ class IssuesFinder < IssuableFinder
def klass
Issue
end
+
+ private
+
+ def init_collection
+ Issue.visible_to_user(current_user)
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index d1b1c61b710..e6ceb213532 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -182,7 +182,7 @@ module ApplicationHelper
# Returns an HTML-safe String
def time_ago_with_tooltip(time, placement: 'top', html_class: 'time_ago', skip_js: false)
element = content_tag :time, time.to_s,
- class: "#{html_class} js-timeago js-timeago-pending",
+ class: "#{html_class} js-timeago #{"js-timeago-pending" unless skip_js}",
datetime: time.to_time.getutc.iso8601,
title: time.in_time_zone.to_s(:medium),
data: { toggle: 'tooltip', placement: placement, container: 'body' }
@@ -196,6 +196,22 @@ module ApplicationHelper
element
end
+ def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', include_author: false)
+ return if object.updated_at == object.created_at
+
+ content_tag :small, class: "edited-text" do
+ output = content_tag(:span, "Edited ")
+ output << time_ago_with_tooltip(object.updated_at, placement: placement, html_class: html_class)
+
+ if include_author && object.updated_by && object.updated_by != object.author
+ output << content_tag(:span, " by ")
+ output << link_to_member(object.project, object.updated_by, avatar: false, author_class: nil)
+ end
+
+ output
+ end
+ end
+
def render_markup(file_name, file_content)
if gitlab_markdown?(file_name)
Haml::Helpers.preserve(markdown(file_content))
@@ -285,7 +301,7 @@ module ApplicationHelper
if project.nil?
nil
elsif current_controller?(:issues)
- project.issues.send(entity).count
+ project.issues.visible_to_user(current_user).send(entity).count
elsif current_controller?(:merge_requests)
project.merge_requests.send(entity).count
end
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 74f326e0b83..ceff1fbb161 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -24,7 +24,7 @@ module DropdownsHelper
capture(&block) if block && !options.has_key?(:footer_content)
end
- if block && options.has_key?(:footer_content)
+ if block && options[:footer_content]
output << content_tag(:div, class: "dropdown-footer") do
capture(&block)
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 37a888d9c60..a67a6b208e2 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -194,7 +194,7 @@ module EventsHelper
end
def event_to_atom(xml, event)
- if event.proper?
+ if event.proper?(current_user)
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 2dfeddf7368..81df2094392 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -20,6 +20,23 @@ module IssuablesHelper
base_issuable_scope(issuable).where('iid < ?', issuable.iid).first
end
+ def user_dropdown_label(user_id, default_label)
+ return "Unassigned" if user_id == "0"
+
+ if @project
+ member = @project.team.find_member(user_id)
+ user = member.user if member
+ else
+ user = User.find_by(id: user_id)
+ end
+
+ if user
+ user.name
+ else
+ default_label
+ end
+ end
+
private
def sidebar_gutter_collapsed?
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index ae4ebc0854a..e00d3204027 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -98,6 +98,10 @@ module IssuesHelper
end.sort.to_sentence(last_word_connector: ', or ')
end
+ def confidential_icon(issue)
+ icon('eye-slash') if issue.confidential?
+ end
+
def emoji_icon(name, unicode = nil, aliases = [])
unicode ||= Emoji.emoji_filename(name) rescue ""
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 4455dcd0e20..ed37176aa6b 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -32,7 +32,7 @@ module LabelsHelper
# link_to_label(label) { "My Custom Label Text" }
#
# Returns a String
- def link_to_label(label, project: nil, type: :issue, &block)
+ def link_to_label(label, project: nil, type: :issue, tooltip: true, &block)
project ||= @project || label.project
link = send("namespace_project_#{type.to_s.pluralize}_path",
project.namespace,
@@ -42,7 +42,7 @@ module LabelsHelper
if block_given?
link_to link, &block
else
- link_to render_colored_label(label), link
+ link_to render_colored_label(label, tooltip: tooltip), link
end
end
@@ -50,23 +50,24 @@ module LabelsHelper
@project.labels.pluck(:title)
end
- def render_colored_label(label, label_suffix = '')
+ def render_colored_label(label, label_suffix = '', tooltip: true)
label_color = label.color || Label::DEFAULT_COLOR
text_color = text_color_for_bg(label_color)
# Intentionally not using content_tag here so that this method can be called
# by LabelReferenceFilter
- span = %(<span class="label color-label") +
- %(style="background-color: #{label_color}; color: #{text_color}">) +
+ span = %(<span class="label color-label #{"has_tooltip" if tooltip}" ) +
+ %(style="background-color: #{label_color}; color: #{text_color}" ) +
+ %(title="#{escape_once(label.description)}" data-container="body">) +
%(#{escape_once(label.name)}#{label_suffix}</span>)
span.html_safe
end
- def render_colored_cross_project_label(label)
+ def render_colored_cross_project_label(label, tooltip: true)
label_suffix = label.project.name_with_namespace
label_suffix = " <i>in #{escape_once(label_suffix)}</i>"
- render_colored_label(label, label_suffix)
+ render_colored_label(label, label_suffix, tooltip: tooltip)
end
def suggested_colors
@@ -109,19 +110,12 @@ module LabelsHelper
end
end
- def projects_labels_options
- labels =
- if @project
- @project.labels
- else
- Label.where(project_id: @projects)
- end
-
- grouped_labels = GlobalLabel.build_collection(labels)
- grouped_labels.unshift(Label::None)
- grouped_labels.unshift(Label::Any)
-
- options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name])
+ def labels_filter_path
+ if @project
+ namespace_project_labels_path(@project.namespace, @project, :json)
+ else
+ labels_dashboard_path(:json)
+ end
end
def label_subscription_status(label)
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index e8ac8788d9d..c9d8787bd19 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -38,7 +38,7 @@ module MilestonesHelper
def milestone_progress_bar(milestone)
options = {
class: 'progress-bar progress-bar-success',
- style: "width: #{milestone.percent_complete}%;"
+ style: "width: #{milestone.percent_complete(current_user)}%;"
}
content_tag :div, class: 'progress' do
@@ -46,22 +46,12 @@ module MilestonesHelper
end
end
- def projects_milestones_options
- milestones =
- if @project
- @project.milestones
- else
- Milestone.where(project_id: @projects)
- end.active
-
- epoch = DateTime.parse('1970-01-01')
- grouped_milestones = GlobalMilestone.build_collection(milestones)
- grouped_milestones = grouped_milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date }
- grouped_milestones.unshift(Milestone::None)
- grouped_milestones.unshift(Milestone::Any)
- grouped_milestones.unshift(Milestone::Upcoming)
-
- options_from_collection_for_select(grouped_milestones, 'name', 'title', params[:milestone_title])
+ def milestones_filter_dropdown_path
+ if @project
+ namespace_project_milestones_path(@project.namespace, @project, :json)
+ else
+ milestones_dashboard_path(:json)
+ end
end
def milestone_remaining_days(milestone)
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index b5acb80b720..5473419ef24 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -26,7 +26,7 @@ module ProjectsHelper
image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar]
end
- def link_to_member(project, author, opts = {})
+ def link_to_member(project, author, opts = {}, &block)
default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" }
opts = default_opts.merge(opts)
@@ -44,6 +44,8 @@ module ProjectsHelper
author_html << content_tag(:span, sanitize(author.name), class: opts[:author_class]) if opts[:name]
end
+ author_html << capture(&block) if block
+
author_html = author_html.html_safe
if opts[:name]
diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb
index 07ddc691d85..edc5686cf08 100644
--- a/app/helpers/todos_helper.rb
+++ b/app/helpers/todos_helper.rb
@@ -16,14 +16,19 @@ module TodosHelper
def todo_target_link(todo)
target = todo.target_type.titleize.downcase
- link_to "#{target} #{todo.target.to_reference}", todo_target_path(todo), { title: h(todo.target.title) }
+ link_to "#{target} #{todo.target_reference}", todo_target_path(todo), { title: todo.target.title }
end
def todo_target_path(todo)
anchor = dom_id(todo.note) if todo.note.present?
- polymorphic_path([todo.project.namespace.becomes(Namespace),
- todo.project, todo.target], anchor: anchor)
+ if todo.for_commit?
+ namespace_project_commit_path(todo.project.namespace.becomes(Namespace), todo.project,
+ todo.target, anchor: anchor)
+ else
+ polymorphic_path([todo.project.namespace.becomes(Namespace),
+ todo.project, todo.target], anchor: anchor)
+ end
end
def todos_filter_params
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 61d5e7dc859..88d7ecf3a16 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -49,7 +49,6 @@ class Ability
rules = [
:read_project,
:read_wiki,
- :read_issue,
:read_label,
:read_milestone,
:read_project_snippet,
@@ -63,6 +62,9 @@ class Ability
# Allow to read builds by anonymous user if guests are allowed
rules << :read_build if project.public_builds?
+ # Allow to read issues by anonymous user if issue is not confidential
+ rules << :read_issue unless subject.is_a?(Issue) && subject.confidential?
+
rules - project_disabled_features_rules(project)
else
[]
@@ -325,6 +327,7 @@ class Ability
end
rules += project_abilities(user, subject.project)
+ rules = filter_confidential_issues_abilities(user, subject, rules) if subject.is_a?(Issue)
rules
end
end
@@ -443,5 +446,17 @@ class Ability
:"admin_#{name}"
]
end
+
+ def filter_confidential_issues_abilities(user, issue, rules)
+ return rules if user.admin? || !issue.confidential?
+
+ unless issue.author == user || issue.assignee == user || issue.project.team.member?(user.id)
+ rules.delete(:admin_issue)
+ rules.delete(:read_issue)
+ rules.delete(:update_issue)
+ end
+
+ rules
+ end
end
end
diff --git a/app/models/abuse_report.rb b/app/models/abuse_report.rb
index cc59aa4e911..b61f5123127 100644
--- a/app/models/abuse_report.rb
+++ b/app/models/abuse_report.rb
@@ -19,9 +19,9 @@ class AbuseReport < ActiveRecord::Base
validates :message, presence: true
validates :user_id, uniqueness: { message: 'has already been reported' }
- def remove_user
+ def remove_user(deleted_by:)
user.block
- user.destroy
+ DeleteUserWorker.perform_async(deleted_by.id, user.id, delete_solo_owned_groups: true)
end
def notify
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 3b1aa0f5c80..3377a85a55a 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -114,7 +114,7 @@ class CommitStatus < ActiveRecord::Base
end
def ignored?
- failed? && allow_failure?
+ allow_failure? && (failed? || canceled?)
end
def duration
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index d67df7c1d9c..5b8e3f654ea 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -1,18 +1,18 @@
module Milestoneish
- def closed_items_count
- issues.closed.size + merge_requests.closed_and_merged.size
+ def closed_items_count(user = nil)
+ issues_visible_to_user(user).closed.size + merge_requests.closed_and_merged.size
end
- def total_items_count
- issues.size + merge_requests.size
+ def total_items_count(user = nil)
+ issues_visible_to_user(user).size + merge_requests.size
end
- def complete?
- total_items_count == closed_items_count
+ def complete?(user = nil)
+ total_items_count(user) == closed_items_count(user)
end
- def percent_complete
- ((closed_items_count * 100) / total_items_count).abs
+ def percent_complete(user = nil)
+ ((closed_items_count(user) * 100) / total_items_count(user)).abs
rescue ZeroDivisionError
0
end
@@ -22,4 +22,8 @@ module Milestoneish
(due_date - Date.today).to_i
end
+
+ def issues_visible_to_user(user = nil)
+ issues.visible_to_user(user)
+ end
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 9a0bbf50f8b..a5cfeaf388e 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -73,15 +73,17 @@ class Event < ActiveRecord::Base
end
end
- def proper?
+ def proper?(user = nil)
if push?
true
elsif membership_changed?
true
elsif created_project?
true
+ elsif issue?
+ Ability.abilities.allowed?(user, :read_issue, issue)
else
- ((issue? || merge_request? || note?) && target) || milestone?
+ ((merge_request? || note?) && target) || milestone?
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 5f58c0508fd..5347d4fa1be 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -58,6 +58,13 @@ class Issue < ActiveRecord::Base
attributes
end
+ def self.visible_to_user(user)
+ return where(confidential: false) if user.blank?
+ return all if user.admin?
+
+ where('issues.confidential = false OR (issues.confidential = true AND (issues.author_id = :user_id OR issues.assignee_id = :user_id OR issues.project_id IN(:project_ids)))', user_id: user.id, project_ids: user.authorized_projects.select(:id))
+ end
+
def self.reference_prefix
'#'
end
@@ -87,11 +94,20 @@ class Issue < ActiveRecord::Base
end
def referenced_merge_requests(current_user = nil)
- Gitlab::ReferenceExtractor.lazily do
- [self, *notes].flat_map do |note|
- note.all_references(current_user).merge_requests
- end
- end.sort_by(&:iid)
+ @referenced_merge_requests ||= {}
+ @referenced_merge_requests[current_user] ||= begin
+ Gitlab::ReferenceExtractor.lazily do
+ [self, *notes].flat_map do |note|
+ note.all_references(current_user).merge_requests
+ end
+ end.sort_by(&:iid).uniq
+ end
+ end
+
+ def related_branches
+ return [] if self.project.empty_repo?
+
+ self.project.repository.branch_names.select { |branch| branch.end_with?("-#{iid}") }
end
# Reset issue events cache
@@ -120,4 +136,15 @@ class Issue < ActiveRecord::Base
note.all_references(current_user).merge_requests
end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
end
+
+ def to_branch_name
+ "#{title.parameterize}-#{iid}"
+ end
+
+ def can_be_worked_on?(current_user)
+ !self.closed? &&
+ !self.project.forked? &&
+ self.related_branches.empty? &&
+ self.closed_by_merge_requests(current_user).empty?
+ end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 188325045e2..a015a9ef394 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -277,8 +277,14 @@ class MergeRequest < ActiveRecord::Base
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end
+ WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
+
def work_in_progress?
- !!(title =~ /\A\[?WIP(\]|:| )/i)
+ title =~ WIP_REGEX
+ end
+
+ def wipless_title
+ self.title.sub(WIP_REGEX, "")
end
def mergeable?
@@ -516,11 +522,15 @@ class MergeRequest < ActiveRecord::Base
end
def target_sha
- @target_sha ||= target_project.repository.commit(target_branch).sha
+ @target_sha ||= target_project.repository.commit(target_branch).try(:sha)
end
def source_sha
- last_commit.try(:sha)
+ last_commit.try(:sha) || source_tip.try(:sha)
+ end
+
+ def source_tip
+ source_branch && source_project.repository.commit(source_branch)
end
def fetch_ref
@@ -568,8 +578,11 @@ class MergeRequest < ActiveRecord::Base
end
def compute_diverged_commits_count
+ return 0 unless source_sha && target_sha
+
Gitlab::Git::Commit.between(target_project.repository.raw_repository, source_sha, target_sha).size
end
+ private :compute_diverged_commits_count
def diverged_from_target_branch?
diverged_commits_count > 0
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 374590ba0c5..de7183bf6b4 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -121,8 +121,8 @@ class Milestone < ActiveRecord::Base
active? && issues.opened.count.zero?
end
- def is_empty?
- total_items_count.zero?
+ def is_empty?(user = nil)
+ total_items_count(user).zero?
end
def author_id
diff --git a/app/models/project.rb b/app/models/project.rb
index 3352959a53d..c1374fc9b3c 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -576,10 +576,7 @@ class Project < ActiveRecord::Base
end
def avatar_in_git
- @avatar_file ||= 'logo.png' if repository.blob_at_branch('master', 'logo.png')
- @avatar_file ||= 'logo.jpg' if repository.blob_at_branch('master', 'logo.jpg')
- @avatar_file ||= 'logo.gif' if repository.blob_at_branch('master', 'logo.gif')
- @avatar_file
+ repository.avatar
end
def avatar_url
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index c96e6f0b8ea..59b1b86d1fb 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -2,7 +2,7 @@ class ProjectWiki
include Gitlab::ShellAdapter
MARKUPS = {
- 'Markdown' => :md,
+ 'Markdown' => :markdown,
'RDoc' => :rdoc,
'AsciiDoc' => :asciidoc
} unless defined?(MARKUPS)
@@ -47,7 +47,7 @@ class ProjectWiki
def wiki
@wiki ||= begin
Gollum::Wiki.new(path_to_repo)
- rescue Gollum::NoSuchPathError
+ rescue Rugged::OSError
create_repo!
end
end
@@ -90,7 +90,7 @@ class ProjectWiki
def create_page(title, content, format = :markdown, message = nil)
commit = commit_details(:created, message, title)
- wiki.write_page(title, format, content, commit)
+ wiki.write_page(title, format.to_sym, content, commit)
update_project_activity
rescue Gollum::DuplicatePageError => e
@@ -101,7 +101,7 @@ class ProjectWiki
def update_page(page, content, format = :markdown, message = nil)
commit = commit_details(:updated, message, page.title)
- wiki.update_page(page, page.name, format, content, commit)
+ wiki.update_page(page, page.name, format.to_sym, content, commit)
update_project_activity
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 6441cd87e87..25d24493f6e 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -3,6 +3,10 @@ require 'securerandom'
class Repository
class CommitError < StandardError; end
+ # Files to use as a project avatar in case no avatar was uploaded via the web
+ # UI.
+ AVATAR_FILES = %w{logo.png logo.jpg logo.gif}
+
include Gitlab::ShellAdapter
attr_accessor :path_with_namespace, :project
@@ -223,12 +227,6 @@ class Repository
send(key)
end
end
-
- branches.each do |branch|
- unless cache.exist?(:"diverging_commit_counts_#{branch.name}")
- send(:diverging_commit_counts, branch)
- end
- end
end
def expire_tags_cache
@@ -241,12 +239,13 @@ class Repository
@branches = nil
end
- def expire_cache(branch_name = nil)
+ def expire_cache(branch_name = nil, revision = nil)
cache_keys.each do |key|
cache.expire(key)
end
expire_branch_cache(branch_name)
+ expire_avatar_cache(branch_name, revision)
# This ensures this particular cache is flushed after the first commit to a
# new repository.
@@ -296,18 +295,6 @@ class Repository
@tag_count = nil
end
- def rebuild_cache
- cache_keys.each do |key|
- cache.expire(key)
- send(key)
- end
-
- branches.each do |branch|
- cache.expire(:"diverging_commit_counts_#{branch.name}")
- diverging_commit_counts(branch)
- end
- end
-
def lookup_cache
@lookup_cache ||= {}
end
@@ -316,6 +303,23 @@ class Repository
cache.expire(:branch_names)
end
+ def expire_avatar_cache(branch_name = nil, revision = nil)
+ # Avatars are pulled from the default branch, thus if somebody pushes to a
+ # different branch there's no need to expire anything.
+ return if branch_name && branch_name != root_ref
+
+ # We don't want to flush the cache if the commit didn't actually make any
+ # changes to any of the possible avatar files.
+ if revision && commit = self.commit(revision)
+ return unless commit.diffs.
+ any? { |diff| AVATAR_FILES.include?(diff.new_path) }
+ end
+
+ cache.expire(:avatar)
+
+ @avatar = nil
+ end
+
# Runs code just before a repository is deleted.
def before_delete
expire_cache if exists?
@@ -350,8 +354,8 @@ class Repository
end
# Runs code after a new commit has been pushed.
- def after_push_commit(branch_name)
- expire_cache(branch_name)
+ def after_push_commit(branch_name, revision)
+ expire_cache(branch_name, revision)
end
# Runs code after a new branch has been created.
@@ -758,12 +762,15 @@ class Repository
def parse_search_result(result)
ref = nil
filename = nil
+ basename = nil
startline = 0
result.each_line.each_with_index do |line, index|
if line =~ /^.*:.*:\d+:/
ref, filename, startline = line.split(':')
startline = startline.to_i - index
+ extname = File.extname(filename)
+ basename = filename.sub(/#{extname}$/, '')
break
end
end
@@ -776,6 +783,7 @@ class Repository
OpenStruct.new(
filename: filename,
+ basename: basename,
ref: ref,
startline: startline,
data: data
@@ -853,6 +861,14 @@ class Repository
end
end
+ def avatar
+ @avatar ||= cache.fetch(:avatar) do
+ AVATAR_FILES.find do |file|
+ blob_at_branch('master', file)
+ end
+ end
+ end
+
private
def cache
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 5f91991f781..d85f7bfdf57 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -5,14 +5,15 @@
# id :integer not null, primary key
# user_id :integer not null
# project_id :integer not null
-# target_id :integer not null
+# target_id :integer
# target_type :string not null
# author_id :integer
-# note_id :integer
# action :integer not null
# state :string not null
# created_at :datetime
# updated_at :datetime
+# note_id :integer
+# commit_id :string
#
class Todo < ActiveRecord::Base
@@ -27,7 +28,9 @@ class Todo < ActiveRecord::Base
delegate :name, :email, to: :author, prefix: true, allow_nil: true
- validates :action, :project, :target, :user, presence: true
+ validates :action, :project, :target_type, :user, presence: true
+ validates :target_id, presence: true, unless: :for_commit?
+ validates :commit_id, presence: true, if: :for_commit?
default_scope { reorder(id: :desc) }
@@ -36,7 +39,7 @@ class Todo < ActiveRecord::Base
state_machine :state, initial: :pending do
event :done do
- transition [:pending, :done] => :done
+ transition [:pending] => :done
end
state :pending
@@ -50,4 +53,25 @@ class Todo < ActiveRecord::Base
target.title
end
end
+
+ def for_commit?
+ target_type == "Commit"
+ end
+
+ # override to return commits, which are not active record
+ def target
+ if for_commit?
+ project.commit(commit_id) rescue nil
+ else
+ super
+ end
+ end
+
+ def target_reference
+ if for_commit?
+ target.short_id
+ else
+ target.to_reference
+ end
+ end
end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index dbd70dc5a44..526760779a4 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -62,7 +62,7 @@ class WikiPage
# The raw content of this page.
def content
@attributes[:content] ||= if @page
- @page.raw_data
+ @page.text_data
end
end
diff --git a/app/services/commits/revert_service.rb b/app/services/commits/revert_service.rb
index 9cb918d7a2e..a3c950ede1f 100644
--- a/app/services/commits/revert_service.rb
+++ b/app/services/commits/revert_service.rb
@@ -9,7 +9,8 @@ module Commits
@commit = params[:commit]
@create_merge_request = params[:create_merge_request].present?
- validate and commit
+ check_push_permissions unless @create_merge_request
+ commit
rescue Repository::CommitError, Gitlab::Git::Repository::InvalidBlobName, GitHooksService::PreReceiveError,
ValidationError, ReversionError => ex
error(ex.message)
@@ -45,11 +46,11 @@ module Commits
end
end
- def validate
+ def check_push_permissions
allowed = ::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(@target_branch)
unless allowed
- raise_error('You are not allowed to push into this branch')
+ raise ValidationError.new('You are not allowed to push into this branch')
end
true
diff --git a/app/services/delete_user_service.rb b/app/services/delete_user_service.rb
index 173e50c9206..ce79287e35a 100644
--- a/app/services/delete_user_service.rb
+++ b/app/services/delete_user_service.rb
@@ -5,18 +5,22 @@ class DeleteUserService
@current_user = current_user
end
- def execute(user)
- if user.solo_owned_groups.present?
+ def execute(user, options = {})
+ if !options[:delete_solo_owned_groups] && user.solo_owned_groups.present?
user.errors[:base] << 'You must transfer ownership or delete groups before you can remove user'
- user
- else
- user.personal_projects.each do |project|
- # Skip repository removal because we remove directory with namespace
- # that contain all this repositories
- ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
- end
+ return user
+ end
+
+ user.solo_owned_groups.each do |group|
+ DestroyGroupService.new(group, current_user).execute
+ end
- user.destroy
+ user.personal_projects.each do |project|
+ # Skip repository removal because we remove directory with namespace
+ # that contain all this repositories
+ ::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
end
+
+ user.destroy
end
end
diff --git a/app/services/destroy_group_service.rb b/app/services/destroy_group_service.rb
index 9189de390a2..3c42ac61be4 100644
--- a/app/services/destroy_group_service.rb
+++ b/app/services/destroy_group_service.rb
@@ -6,12 +6,12 @@ class DestroyGroupService
end
def execute
- @group.projects.each do |project|
+ group.projects.each do |project|
# Skip repository removal because we remove directory with namespace
# that contain all this repositories
::Projects::DestroyService.new(project, current_user, skip_repo: true).pending_delete!
end
- @group.destroy
+ group.destroy
end
end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index d840ab5e340..14e2a2c0699 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -17,7 +17,7 @@ class GitPushService < BaseService
# 6. Checks if the project's main language has changed
#
def execute
- @project.repository.after_push_commit(branch_name)
+ @project.repository.after_push_commit(branch_name, params[:newrev])
if push_remove_branch?
@project.repository.after_remove_branch
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 7b306a8a531..ac5b58db862 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -5,6 +5,19 @@ module MergeRequests
SystemNoteService.change_status(merge_request, merge_request.target_project, current_user, merge_request.state, nil)
end
+ def create_title_change_note(issuable, old_title)
+ removed_wip = old_title =~ MergeRequest::WIP_REGEX && !issuable.work_in_progress?
+ added_wip = old_title !~ MergeRequest::WIP_REGEX && issuable.work_in_progress?
+
+ if removed_wip
+ SystemNoteService.remove_merge_request_wip(issuable, issuable.project, current_user)
+ elsif added_wip
+ SystemNoteService.add_merge_request_wip(issuable, issuable.project, current_user)
+ else
+ super
+ end
+ end
+
def hook_data(merge_request, action)
hook_data = merge_request.to_hook_data(current_user)
merge_request_url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id)
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 954746a39a5..6e9152e444e 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -47,6 +47,21 @@ module MergeRequests
merge_request.title = merge_request.source_branch.titleize.humanize
end
+ # When your branch name starts with an iid followed by a dash this pattern will
+ # be interpreted as the use wants to close that issue on this project
+ # Pattern example: 112-fix-mep-mep
+ # Will lead to appending `Closes #112` to the description
+ if match = merge_request.source_branch.match(/-(\d+)\z/)
+ iid = match[1]
+ closes_issue = "Closes ##{iid}"
+
+ if merge_request.description.present?
+ merge_request.description << closes_issue.prepend("\n")
+ else
+ merge_request.description = closes_issue
+ end
+ end
+
merge_request
end
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index 7408e09ed1e..ba50305dbd5 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -1,11 +1,7 @@
module Projects
class AutocompleteService < BaseService
- def initialize(project)
- @project = project
- end
-
def issues
- @project.issues.opened.select([:iid, :title])
+ @project.issues.visible_to_user(current_user).opened.select([:iid, :title])
end
def merge_requests
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index bccd67d3dbf..a0973c5d260 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -24,7 +24,7 @@ module Projects
def execute
raise LeaseTaken if !try_obtain_lease
- GitlabShellWorker.perform_async(:gc, @project.path_with_namespace)
+ GitlabShellOneShotWorker.perform_async(:gc, @project.path_with_namespace)
ensure
@project.update_column(:pushes_since_gc, 0)
end
diff --git a/app/services/search/global_service.rb b/app/services/search/global_service.rb
index e1e94c5cc38..aa9837038a6 100644
--- a/app/services/search/global_service.rb
+++ b/app/services/search/global_service.rb
@@ -11,7 +11,7 @@ module Search
projects = ProjectsFinder.new.execute(current_user)
projects = projects.in_namespace(group.id) if group
- Gitlab::SearchResults.new(projects, params[:search])
+ Gitlab::SearchResults.new(current_user, projects, params[:search])
end
end
end
diff --git a/app/services/search/project_service.rb b/app/services/search/project_service.rb
index c08881dce4b..4b500914cfb 100644
--- a/app/services/search/project_service.rb
+++ b/app/services/search/project_service.rb
@@ -7,7 +7,8 @@ module Search
end
def execute
- Gitlab::ProjectSearchResults.new(project,
+ Gitlab::ProjectSearchResults.new(current_user,
+ project,
params[:search],
params[:repository_ref])
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 58a861ee08e..c644cd0b951 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -144,6 +144,18 @@ class SystemNoteService
create_note(noteable: noteable, project: project, author: author, note: body)
end
+ def self.remove_merge_request_wip(noteable, project, author)
+ body = 'Unmarked this merge request as a Work In Progress'
+
+ create_note(noteable: noteable, project: project, author: author, note: body)
+ end
+
+ def self.add_merge_request_wip(noteable, project, author)
+ body = 'Marked this merge request as a **Work In Progress**'
+
+ create_note(noteable: noteable, project: project, author: author, note: body)
+ end
+
# Called when the title of a Noteable is changed
#
# noteable - Noteable object that responds to `title`
@@ -207,6 +219,18 @@ class SystemNoteService
create_note(noteable: noteable, project: project, author: author, note: body)
end
+ # Called when a branch is created from the 'new branch' button on a issue
+ # Example note text:
+ #
+ # "Started branch `issue-branch-button-201`"
+ def self.new_issue_branch(issue, project, author, branch)
+ h = Gitlab::Application.routes.url_helpers
+ link = h.namespace_project_compare_url(project.namespace, project, from: project.default_branch, to: branch)
+
+ body = "Started branch [`#{branch}`](#{link})"
+ create_note(noteable: issue, project: project, author: author, note: body)
+ end
+
# Called when a Mentionable references a Noteable
#
# noteable - Noteable object being referenced
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 4392e2d17fe..f2662922e90 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -103,24 +103,16 @@ class TodoService
# * mark all pending todos related to the target for the current user as done
#
def mark_pending_todos_as_done(target, user)
- pending_todos(user, target.project, target).update_all(state: :done)
+ attributes = attributes_for_target(target)
+ pending_todos(user, attributes).update_all(state: :done)
end
private
- def create_todos(project, target, author, users, action, note = nil)
+ def create_todos(users, attributes)
Array(users).each do |user|
- next if pending_todos(user, project, target).exists?
-
- Todo.create(
- project: project,
- user_id: user.id,
- author_id: author.id,
- target_id: target.id,
- target_type: target.class.name,
- action: action,
- note: note
- )
+ next if pending_todos(user, attributes).exists?
+ Todo.create(attributes.merge(user_id: user.id))
end
end
@@ -130,8 +122,8 @@ class TodoService
end
def handle_note(note, author)
- # Skip system notes, notes on commit, and notes on project snippet
- return if note.system? || ['Commit', 'Snippet'].include?(note.noteable_type)
+ # Skip system notes, and notes on project snippet
+ return if note.system? || note.for_project_snippet?
project = note.project
target = note.noteable
@@ -142,13 +134,39 @@ class TodoService
def create_assignment_todo(issuable, author)
if issuable.assignee && issuable.assignee != author
- create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED)
+ attributes = attributes_for_todo(issuable.project, issuable, author, Todo::ASSIGNED)
+ create_todos(issuable.assignee, attributes)
end
end
- def create_mention_todos(project, issuable, author, note = nil)
- mentioned_users = filter_mentioned_users(project, note || issuable, author)
- create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note)
+ def create_mention_todos(project, target, author, note = nil)
+ mentioned_users = filter_mentioned_users(project, note || target, author)
+ attributes = attributes_for_todo(project, target, author, Todo::MENTIONED, note)
+ create_todos(mentioned_users, attributes)
+ end
+
+ def attributes_for_target(target)
+ attributes = {
+ project_id: target.project.id,
+ target_id: target.id,
+ target_type: target.class.name,
+ commit_id: nil
+ }
+
+ if target.is_a?(Commit)
+ attributes.merge!(target_id: nil, commit_id: target.id)
+ end
+
+ attributes
+ end
+
+ def attributes_for_todo(project, target, author, action, note = nil)
+ attributes_for_target(target).merge!(
+ project_id: project.id,
+ author_id: author.id,
+ action: action,
+ note: note
+ )
end
def filter_mentioned_users(project, target, author)
@@ -160,11 +178,8 @@ class TodoService
mentioned_users.uniq
end
- def pending_todos(user, project, target)
- user.todos.pending.where(
- project_id: project.id,
- target_id: target.id,
- target_type: target.class.name
- )
+ def pending_todos(user, criteria = {})
+ valid_keys = [:project_id, :target_id, :target_type, :commit_id]
+ user.todos.pending.where(criteria.slice(*valid_keys))
end
end
diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml
index 5736a301910..f417b2e44a4 100644
--- a/app/views/admin/labels/_label.html.haml
+++ b/app/views/admin/labels/_label.html.haml
@@ -1,6 +1,6 @@
%li{id: dom_id(label)}
.label-row
- = render_colored_label(label)
+ = render_colored_label(label, tooltip: false)
= markdown(label.description, pipeline: :single_line)
.pull-right
= link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm'
diff --git a/app/views/dashboard/todos/_todo.html.haml b/app/views/dashboard/todos/_todo.html.haml
index 45cfe3da188..e3a4d64df01 100644
--- a/app/views/dashboard/todos/_todo.html.haml
+++ b/app/views/dashboard/todos/_todo.html.haml
@@ -2,7 +2,7 @@
.todo-item.todo-block
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
- .todo-title
+ .todo-title.title
%span.author-name
- if todo.author
= link_to_author(todo)
@@ -16,7 +16,9 @@
- if todo.pending?
.todo-actions.pull-right
- = link_to 'Done', [:dashboard, todo], method: :delete, class: 'btn'
+ = link_to [:dashboard, todo], method: :delete, class: 'btn btn-loading done-todo' do
+ Done
+ = icon('spinner spin')
.todo-body
.todo-note
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 946d7df3933..f9ec3a89158 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -3,13 +3,15 @@
.top-area
%ul.nav-links
- %li{class: ('active' if params[:state].blank? || params[:state] == 'pending')}
+ - todo_pending_active = ('active' if params[:state].blank? || params[:state] == 'pending')
+ %li{class: "todos-pending #{todo_pending_active}"}
= link_to todos_filter_path(state: 'pending') do
%span
To do
%span{class: 'badge'}
= todos_pending_count
- %li{class: ('active' if params[:state] == 'done')}
+ - todo_done_active = ('active' if params[:state] == 'done')
+ %li{class: "todos-done #{todo_done_active}"}
= link_to todos_filter_path(state: 'done') do
%span
Done
@@ -18,7 +20,9 @@
.nav-controls
- if @todos.any?(&:pending?)
- = link_to 'Mark all as done', destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn', method: :delete
+ = link_to destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn btn-loading js-todos-mark-all', method: :delete do
+ Mark all as done
+ = icon('spinner spin')
.todos-filters
.gray-content-block.second-block
@@ -42,12 +46,12 @@
.prepend-top-default
- if @todos.any?
- @todos.group_by(&:project).each do |group|
- .panel.panel-default.panel-small
+ .panel.panel-default.panel-small.js-todos-list
- project = group[0]
.panel-heading
= link_to project.name_with_namespace, namespace_project_path(project.namespace, project)
- %ul.well-list.todos-list
+ %ul.content-list.todos-list
= render group[1]
= paginate @todos, theme: "gitlab"
- else
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 36fb2d51629..2d9d9dd6342 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,4 +1,4 @@
-- if event.proper?
+- if event.proper?(current_user)
.event-item{class: "#{event.body? ? "event-block" : "event-inline" }"}
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 714da410f56..bfa5937cf3f 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -45,6 +45,8 @@
%h1.title= title
= render 'shared/outdated_browser'
+
- if @project && !@project.empty_repo?
- :javascript
- var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}";
+ - if ref = @ref || @project.repository.root_ref
+ :javascript
+ var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, ref)}";
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 0ae83ee01eb..86b46e8c75e 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -67,7 +67,7 @@
%span
Issues
- if @project.default_issues_tracker?
- %span.count.issue_counter= number_with_delimiter(@project.issues.opened.count)
+ %span.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
diff --git a/app/views/projects/_builds_settings.html.haml b/app/views/projects/_builds_settings.html.haml
new file mode 100644
index 00000000000..95ab9ecf3e8
--- /dev/null
+++ b/app/views/projects/_builds_settings.html.haml
@@ -0,0 +1,60 @@
+%fieldset.builds-feature
+ %legend
+ Builds:
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ %p Get recent application code using the following command:
+ .radio
+ = f.label :build_allow_git_fetch_false do
+ = f.radio_button :build_allow_git_fetch, 'false'
+ %strong git clone
+ %br
+ %span.descr Slower but makes sure you have a clean dir before every build
+ .radio
+ = f.label :build_allow_git_fetch_true do
+ = f.radio_button :build_allow_git_fetch, 'true'
+ %strong git fetch
+ %br
+ %span.descr Faster
+
+ .form-group
+ = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
+ .col-sm-10
+ = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
+ %p.help-block per build in minutes
+ .form-group
+ = f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label'
+ .col-sm-10
+ .input-group
+ %span.input-group-addon /
+ = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
+ %span.input-group-addon /
+ %p.help-block
+ We will use this regular expression to find test coverage output in build trace.
+ Leave blank if you want to disable this feature
+ .bs-callout.bs-callout-info
+ %p Below are examples of regex for existing tools:
+ %ul
+ %li
+ Simplecov (Ruby) -
+ %code \(\d+.\d+\%\) covered
+ %li
+ pytest-cov (Python) -
+ %code \d+\%\s*$
+ %li
+ phpunit --coverage-text --colors=never (PHP) -
+ %code ^\s*Lines:\s*\d+.\d+\%
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :public_builds do
+ = f.check_box :public_builds
+ %strong Public builds
+ .help-block Allow everyone to access builds for Public and Internal projects
+
+ .form-group
+ = f.label :runners_token, "Runners token", class: 'control-label'
+ .col-sm-10
+ = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
+ %p.help-block The secure token used to checkout project.
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 6086ad3661e..2e1a37aa06d 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -20,4 +20,4 @@
- next unless blob
= render 'projects/diffs/file', i: index, project: project,
- diff_file: diff_file, diff_commit: diff_commit, blob: blob
+ diff_file: diff_file, diff_commit: diff_commit, blob: blob, diff_refs: diff_refs
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 3ac058a3bf8..3898bb202c5 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -42,13 +42,17 @@
.diff-content.diff-wrap-lines
-# Skipp all non non-supported blobs
- return unless blob.respond_to?('text?')
- - if blob_text_viewable?(blob)
- - if diff_view == 'parallel'
- = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
- - else
- = render "projects/diffs/text_file", diff_file: diff_file, index: i
- - elsif blob.image?
- - old_file = project.repository.prev_blob_for_diff(diff_commit, diff_file)
- = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i
+ - if diff_file.too_large?
+ .nothing-here-block
+ This diff could not be displayed because it is too large.
- else
- .nothing-here-block No preview for this file type
+ - if blob_text_viewable?(blob)
+ - if diff_view == 'parallel'
+ = render "projects/diffs/parallel_view", diff_file: diff_file, project: project, blob: blob, index: i
+ - else
+ = render "projects/diffs/text_file", diff_file: diff_file, index: i
+ - elsif blob.image?
+ - old_file = project.repository.prev_blob_for_diff(diff_commit, diff_file)
+ = render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i, diff_refs: diff_refs
+ - else
+ .nothing-here-block No preview for this file type
diff --git a/app/views/projects/diffs/_image.html.haml b/app/views/projects/diffs/_image.html.haml
index 752e92e2e6b..8367112a9cb 100644
--- a/app/views/projects/diffs/_image.html.haml
+++ b/app/views/projects/diffs/_image.html.haml
@@ -1,6 +1,7 @@
- diff = diff_file.diff
- file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.id, diff.new_path))
-- old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path))
+- old_commit_id = diff_refs.first.id
+- old_file_raw_path = namespace_project_raw_path(@project.namespace, @project, tree_join(old_commit_id, diff.old_path))
- if diff.renamed_file || diff.new_file || diff.deleted_file
.image
%span.wrap
@@ -12,7 +13,7 @@
%div.two-up.view
%span.wrap
.frame.deleted
- %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(@commit.parent_id, diff.old_path))}
+ %a{href: namespace_project_blob_path(@project.namespace, @project, tree_join(old_commit_id, diff.old_path))}
%img{src: old_file_raw_path}
%p.image-info.hide
%span.meta-filesize= "#{number_to_human_size old_file.size}"
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index f2e56081afe..6d872cd0b21 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -84,6 +84,8 @@
%br
%span.descr Share code pastes with others out of git repository
+ = render 'builds_settings', f: f
+
%fieldset.features
%legend
Project avatar:
@@ -110,69 +112,6 @@
%hr
= link_to 'Remove avatar', namespace_project_avatar_path(@project.namespace, @project), data: { confirm: "Project avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
- %fieldset.features
- %legend
- Continuous Integration
- .form-group
- .col-sm-offset-2.col-sm-10
- %p Get recent application code using the following command:
- .radio
- = f.label :build_allow_git_fetch_false do
- = f.radio_button :build_allow_git_fetch, 'false'
- %strong git clone
- %br
- %span.descr Slower but makes sure you have a clean dir before every build
- .radio
- = f.label :build_allow_git_fetch_true do
- = f.radio_button :build_allow_git_fetch, 'true'
- %strong git fetch
- %br
- %span.descr Faster
-
- .form-group
- = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
- .col-sm-10
- = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
- %p.help-block per build in minutes
- .form-group
- = f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label'
- .col-sm-10
- .input-group
- %span.input-group-addon /
- = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
- %span.input-group-addon /
- %p.help-block
- We will use this regular expression to find test coverage output in build trace.
- Leave blank if you want to disable this feature
- .bs-callout.bs-callout-info
- %p Below are examples of regex for existing tools:
- %ul
- %li
- Simplecov (Ruby) -
- %code \(\d+.\d+\%\) covered
- %li
- pytest-cov (Python) -
- %code \d+\%\s*$
- %li
- phpunit --coverage-text --colors=never (PHP) -
- %code ^\s*Lines:\s*\d+.\d+\%
-
- .form-group
- .col-sm-offset-2.col-sm-10
- .checkbox
- = f.label :public_builds do
- = f.check_box :public_builds
- %strong Public builds
- .help-block Allow everyone to access builds for Public and Internal projects
-
- %fieldset.features
- %legend
- Advanced settings
- .form-group
- = f.label :runners_token, "CI token", class: 'control-label'
- .col-sm-10
- = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
- %p.help-block The secure token used to checkout project.
.form-actions
= f.submit 'Save changes', class: "btn btn-save"
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index a44f34c2a68..4aa92d0b39e 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -3,10 +3,11 @@
.issue-check
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue"
- .issue-title
+ .issue-title.title
%span.issue-title-text
- = link_to_gfm issue.title, issue_path(issue), class: "title"
- %ul.controls.light
+ = confidential_icon(issue)
+ = link_to_gfm issue.title, issue_path(issue)
+ %ul.controls
- if issue.closed?
%li
CLOSED
diff --git a/app/views/projects/issues/_merge_requests.html.haml b/app/views/projects/issues/_merge_requests.html.haml
index d9868ad1f0a..d6b38b327ff 100644
--- a/app/views/projects/issues/_merge_requests.html.haml
+++ b/app/views/projects/issues/_merge_requests.html.haml
@@ -1,4 +1,4 @@
--if @merge_requests.any?
+- if @merge_requests.any?
%h2.merge-requests-title
= pluralize(@merge_requests.count, 'Related Merge Request')
%ul.unstyled-list
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
new file mode 100644
index 00000000000..e66e4669d48
--- /dev/null
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -0,0 +1,5 @@
+- if current_user && can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
+ .pull-right
+ = link_to namespace_project_branches_path(@project.namespace, @project, branch_name: @issue.to_branch_name, issue_iid: @issue.iid), method: :post, class: 'btn', title: @issue.to_branch_name do
+ = icon('code-fork')
+ New Branch
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
new file mode 100644
index 00000000000..b10cd03515f
--- /dev/null
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -0,0 +1,15 @@
+- if @related_branches.any?
+ %h2.related-branches-title
+ = pluralize(@related_branches.count, 'Related Branch')
+ %ul.unstyled-list
+ - @related_branches.each do |branch|
+ %li
+ - sha = @project.repository.find_branch(branch).target
+ - ci_commit = @project.ci_commit(sha) if sha
+ - if ci_commit
+ %span.related-branch-ci-status
+ = render_ci_status(ci_commit)
+ %span.related-branch-info
+ %strong
+ = link_to namespace_project_compare_path(@project.namespace, @project, from: @project.default_branch, to: branch), class: "label-branch" do
+ = branch
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 0242276cd84..52df3de8a27 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -22,20 +22,20 @@
= icon('angle-double-left')
.issue-meta
+ = confidential_icon(@issue)
%strong.identifier
Issue ##{@issue.iid}
%span.creator
- by
+ opened
.editor-details
.editor-details
+ = time_ago_with_tooltip(@issue.created_at)
+ by
%strong
= link_to_member(@project, @issue.author, size: 24, mobile_classes: "hidden-xs")
- %span.hidden-xs
- = '@' + @issue.author.username
%strong
= link_to_member(@project, @issue.author, size: 24, mobile_classes: "hidden-sm hidden-md hidden-lg",
by_username: true, avatar: false)
- = time_ago_with_tooltip(@issue.created_at)
.pull-right.issue-btn-group
- if can?(current_user, :create_issue, @project)
@@ -63,15 +63,14 @@
= markdown(@issue.description, cache_key: [@issue, "description"])
%textarea.hidden.js-task-list-field
= @issue.description
- - if @issue.updated_at != @issue.created_at
- %small
- Edited
- = time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
+ = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago')
.merge-requests
= render 'merge_requests'
+ = render 'related_branches'
.content-block.content-block-small
+ = render 'new_branch'
= render 'votes/votes_block', votable: @issue
.row
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 18cf3f14f0b..13d0cbdde1d 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,8 +1,8 @@
%li{ class: mr_css_classes(merge_request) }
- .merge-request-title
+ .merge-request-title.title
%span.merge-request-title-text
- = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "title"
- %ul.controls.light
+ = link_to_gfm merge_request.title, merge_request_path(merge_request)
+ %ul.controls
- if merge_request.merged?
%li
MERGED
diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml
index 602f787e6cf..a23bd8d18d0 100644
--- a/app/views/projects/merge_requests/show/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_box.html.haml
@@ -11,7 +11,4 @@
%textarea.hidden.js-task-list-field
= @merge_request.description
- - if @merge_request.updated_at != @merge_request.created_at
- %small
- Edited
- = time_ago_with_tooltip(@merge_request.updated_at, placement: 'bottom')
+ = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom')
diff --git a/app/views/projects/merge_requests/show/_mr_title.html.haml b/app/views/projects/merge_requests/show/_mr_title.html.haml
index a75c0d96c57..eeb605e2dc5 100644
--- a/app/views/projects/merge_requests/show/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/show/_mr_title.html.haml
@@ -8,18 +8,21 @@
= icon('angle-double-left')
.issue-meta
%strong.identifier
- Merge Request ##{@merge_request.iid}
+ %span.hidden-sm.hidden-md.hidden-lg
+ MR
+ %span.hidden-xs
+ Merge Request
+ !#{@merge_request.iid}
%span.creator
- by
+ opened
.editor-details
+ = time_ago_with_tooltip(@merge_request.created_at)
+ by
%strong
= link_to_member(@project, @merge_request.author, size: 24, mobile_classes: "hidden-xs")
- %span.hidden-xs
- = '@' + @merge_request.author.username
%strong
= link_to_member(@project, @merge_request.author, size: 24, mobile_classes: "hidden-sm hidden-md hidden-lg",
by_username: true, avatar: false)
- = time_ago_with_tooltip(@merge_request.created_at)
.issue-btn-group.pull-right
- if can?(current_user, :update_merge_request, @merge_request)
diff --git a/app/views/projects/merge_requests/widget/open/_wip.html.haml b/app/views/projects/merge_requests/widget/open/_wip.html.haml
index 0cf16542cc1..c296422a9cf 100644
--- a/app/views/projects/merge_requests/widget/open/_wip.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_wip.html.haml
@@ -1,5 +1,11 @@
%h4
This merge request is currently a Work In Progress
-%p
- When this merge request is ready, remove the "WIP" prefix from the title to allow it to be merged.
+- if can?(current_user, :update_merge_request, @merge_request)
+ %p
+ When this merge request is ready,
+ = link_to remove_wip_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), method: :post do
+ remove the
+ %code WIP:
+ prefix from the title
+ to allow it to be merged.
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index b4597043a27..be63875ab34 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -42,7 +42,7 @@
= preserve do
= markdown @milestone.description
-- if @milestone.complete? && @milestone.active?
+- if @milestone.complete?(current_user) && @milestone.active?
.alert.alert-success.prepend-top-default
%span All issues for this milestone are closed. You may close milestone now.
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 52972576aff..2cf32e6093d 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -27,20 +27,13 @@
%span.note-last-update
%a{name: dom_id(note), href: "##{dom_id(note)}", title: 'Link here'}
= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note_created_ago')
- - if note.updated_at != note.created_at
- %span.note-updated-at
- &middot;
- = icon('edit', title: 'edited')
- = time_ago_with_tooltip(note.updated_at, placement: 'bottom', html_class: 'note_edited_ago')
- - if note.updated_by && note.updated_by != note.author
- by #{link_to_member(note.project, note.updated_by, avatar: false, author_class: nil)}
-
.note-body{class: note_editable?(note) ? 'js-task-list-container' : ''}
.note-text
= preserve do
= markdown(note.note, pipeline: :note, cache_key: [note, "note"])
- if note_editable?(note)
= render 'projects/notes/edit_form', note: note
+ = edited_time_ago_with_tooltip(note, placement: 'bottom', html_class: 'note_edited_ago', include_author: true)
- if note.attachment.url
.note-attachment
@@ -54,4 +47,3 @@
= link_to delete_attachment_namespace_project_note_path(note.project.namespace, note.project, note),
title: 'Delete this attachment', method: :delete, remote: true, data: { confirm: 'Are you sure you want to remove the attachment?' }, class: 'danger js-note-attachment-delete' do
= icon('trash-o', class: 'cred')
- .clear
diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml
index b9486a9b492..24658319060 100644
--- a/app/views/projects/repositories/_download_archive.html.haml
+++ b/app/views/projects/repositories/_download_archive.html.haml
@@ -10,7 +10,7 @@
%span.caret
%span.sr-only
Select Archive Format
- %ul.col-xs-10.dropdown-menu{ role: 'menu' }
+ %ul.col-xs-10.dropdown-menu.dropdown-menu-align-right{ role: 'menu' }
%li
= link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), rel: 'nofollow' do
%i.fa.fa-download
diff --git a/app/views/search/results/_issue.html.haml b/app/views/search/results/_issue.html.haml
index 45d700781f3..710f5613c81 100644
--- a/app/views/search/results/_issue.html.haml
+++ b/app/views/search/results/_issue.html.haml
@@ -1,5 +1,6 @@
.search-result-row
%h4
+ = confidential_icon(issue)
= link_to [issue.project.namespace.becomes(Namespace), issue.project, issue] do
%span.term.str-truncated= issue.title
.pull-right ##{issue.iid}
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index f5859481d46..235106c4f74 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -2,9 +2,9 @@
.blob-result
.file-holder
.file-title
- = link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.filename) do
+ = link_to namespace_project_wiki_path(@project.namespace, @project, wiki_blob.basename) do
%i.fa.fa-file
%strong
- = wiki_blob.filename
+ = wiki_blob.basename
.file-content.code.term
= render 'shared/file_highlight', blob: wiki_blob, first_line_number: wiki_blob.startline
diff --git a/app/views/shared/_label_row.html.haml b/app/views/shared/_label_row.html.haml
index 8134b15d245..4b47b0291be 100644
--- a/app/views/shared/_label_row.html.haml
+++ b/app/views/shared/_label_row.html.haml
@@ -1,4 +1,4 @@
%span.label-row
- = link_to_label(label)
+ = link_to_label(label, tooltip: false)
%span.prepend-left-10
= markdown(label.description, pipeline: :single_line)
diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml
index 82eeb2088c8..67a59f420f3 100644
--- a/app/views/shared/groups/_group.html.haml
+++ b/app/views/shared/groups/_group.html.haml
@@ -10,7 +10,7 @@
%i.fa.fa-cogs
= link_to leave_group_group_members_path(group), data: { confirm: leave_group_message(group.name) }, method: :delete, class: "btn-sm btn btn-grouped", title: 'Leave this group' do
- %i.fa.fa-sign-out
+ = icon('sign-out')
.stats
%span
@@ -25,12 +25,13 @@
= visibility_level_icon(group.visibility_level, fw: false)
= image_tag group_icon(group), class: "avatar s40 hidden-xs"
- = link_to group, class: 'group-name title' do
- = group.name
+ .title
+ = link_to group, class: 'group-name' do
+ = group.name
- - if group_member
- as
- %span #{group_member.human_access}
+ - if group_member
+ as
+ %span #{group_member.human_access}
- if group.description.present?
.description
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index 42a3c2c3f02..ac20f7d1f7e 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -9,75 +9,20 @@
.filter-item.inline
- if params[:author_id]
= hidden_field_tag(:author_id, params[:author_id])
- = dropdown_tag("Author", options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id" } })
+ = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author",
+ placeholder: "Search authors", data: { any_user: "Any Author", first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
.filter-item.inline
- if params[:assignee_id]
= hidden_field_tag(:assignee_id, params[:assignee_id])
- = dropdown_tag("Assignee", options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee",
- placeholder: "Search assignee", data: { any_user: "Any Author", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id" } })
+ = dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee",
+ placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: (current_user.username if current_user), null_user: true, current_user: true, project_id: (@project.id if @project), selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
.filter-item.inline.milestone-filter
- - if params[:milestone_title]
- = hidden_field_tag(:milestone_title, params[:milestone_title])
- = dropdown_tag("Milestone", options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
- placeholder: "Search milestones", footer_content: true, data: { show_no: true, show_any: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: (@project.id if @project), milestones: (namespace_project_milestones_path(@project.namespace, @project, :js) if @project) } }) do
- - if @project
- %ul.dropdown-footer-list
- - if can? current_user, :admin_milestone, @project
- %li
- = link_to new_namespace_project_milestone_path(@project.namespace, @project), title: "New Milestone" do
- Create new
- %li
- = link_to namespace_project_milestones_path(@project.namespace, @project) do
- - if can? current_user, :admin_milestone, @project
- Manage milestones
- - else
- View milestones
+ = render "shared/issuable/milestone_dropdown"
.filter-item.inline.labels-filter
- - if params[:label_name]
- = hidden_field_tag(:label_name, params[:label_name])
- .dropdown
- %button.dropdown-menu-toggle.js-label-select.js-filter-submit{type: "button", data: {toggle: "dropdown", field_name: "label_name", show_no: "true", show_any: "true", selected: params[:label_name], project_id: (@project.id if @project), labels: (namespace_project_labels_path(@project.namespace, @project, :js) if @project)}}
- %span.dropdown-toggle-text
- Label
- = icon('chevron-down')
- .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
- .dropdown-page-one
- = dropdown_title("Filter by label")
- = dropdown_filter("Search labels")
- = dropdown_content
- - if @project
- = dropdown_footer do
- %ul.dropdown-footer-list
- - if can? current_user, :admin_label, @project
- %li
- %a.dropdown-toggle-page{href: "#"}
- Create new
- %li
- = link_to namespace_project_labels_path(@project.namespace, @project) do
- - if can? current_user, :admin_label, @project
- Manage labels
- - else
- View labels
- - if can? current_user, :admin_label, @project
- .dropdown-page-two
- = dropdown_title("Create new label", back: true)
- = dropdown_content do
- %input#new_label_color{type: "hidden"}
- %input#new_label_name.dropdown-input-field{type: "text", placeholder: "Name new label"}
- .dropdown-label-color-preview.js-dropdown-label-color-preview
- .suggest-colors.suggest-colors-dropdown
- - suggested_colors.each do |color|
- = link_to '#', style: "background-color: #{color}", data: { color: color } do
- &nbsp
- %button.btn.btn-primary.js-new-label-btn{type: "button"}
- Create
- = dropdown_loading
- .dropdown-loading
- = icon('spinner spin')
+ = render "shared/issuable/label_dropdown"
.pull-right
= render 'shared/sort_dropdown'
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index d5a4aad05d9..80418e69d9c 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -13,12 +13,21 @@
- if issuable.is_a?(MergeRequest)
%p.help-block
- - if issuable.work_in_progress?
- Remove the <code>WIP</code> prefix from the title to allow this
- <strong>Work In Progress</strong> merge request to be merged when it's ready.
- - else
- Start the title with <code>[WIP]</code> or <code>WIP:</code> to prevent a
- <strong>Work In Progress</strong> merge request from being merged before it's ready.
+ .js-wip-explanation
+ %a.js-toggle-wip{href: ""}
+ Remove the
+ %code WIP:
+ prefix from the title
+ to allow this
+ %strong Work In Progress
+ merge request to be merged when it's ready.
+ .js-no-wip-explanation
+ %a.js-toggle-wip{href: ""}
+ Start the title with
+ %code WIP:
+ to prevent a
+ %strong Work In Progress
+ merge request from being merged before it's ready.
.form-group.detail-page-description
= f.label :description, 'Description', class: 'control-label'
.col-sm-10
@@ -29,6 +38,15 @@
= render 'projects/notes/hints'
.clearfix
.error-alert
+
+- if issuable.is_a?(Issue) && !issuable.project.private?
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :confidential do
+ = f.check_box :confidential
+ This issue is confidential and should only be visible to team members
+
- if can?(current_user, :"admin_#{issuable.to_ability_name}", issuable.project)
%hr
.form-group
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
new file mode 100644
index 00000000000..87617315181
--- /dev/null
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -0,0 +1,39 @@
+- if params[:label_name]
+ = hidden_field_tag(:label_name, params[:label_name])
+.dropdown
+ %button.dropdown-menu-toggle.js-label-select.js-filter-submit{type: "button", data: {toggle: "dropdown", field_name: "label_name", show_no: "true", show_any: "true", selected: params[:label_name], project_id: @project.try(:id), labels: labels_filter_path, default_label: "Label"}}
+ %span.dropdown-toggle-text
+ = h(params[:label_name].presence || "Label")
+ = icon('chevron-down')
+ .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable
+ .dropdown-page-one
+ = dropdown_title("Filter by label")
+ = dropdown_filter("Search labels")
+ = dropdown_content
+ - if @project
+ = dropdown_footer do
+ %ul.dropdown-footer-list
+ - if can? current_user, :admin_label, @project
+ %li
+ %a.dropdown-toggle-page{href: "#"}
+ Create new
+ %li
+ = link_to namespace_project_labels_path(@project.namespace, @project) do
+ - if can? current_user, :admin_label, @project
+ Manage labels
+ - else
+ View labels
+ - if can? current_user, :admin_label, @project and @project
+ .dropdown-page-two
+ = dropdown_title("Create new label", back: true)
+ = dropdown_content do
+ %input#new_label_color{type: "hidden"}
+ %input#new_label_name.dropdown-input-field{type: "text", placeholder: "Name new label"}
+ .dropdown-label-color-preview.js-dropdown-label-color-preview
+ .suggest-colors.suggest-colors-dropdown
+ - suggested_colors.each do |color|
+ = link_to '#', style: "background-color: #{color}", data: { color: color } do
+ &nbsp
+ %button.btn.btn-primary.js-new-label-btn{type: "button"}
+ Create
+ = dropdown_loading
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
new file mode 100644
index 00000000000..0434506c8d7
--- /dev/null
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -0,0 +1,16 @@
+- if params[:milestone_title]
+ = hidden_field_tag(:milestone_title, params[:milestone_title])
+= dropdown_tag(h(params[:milestone_title].presence || "Milestone"), options: { title: "Filter by milestone", toggle_class: 'js-milestone-select js-filter-submit', filter: true, dropdown_class: "dropdown-menu-selectable",
+ placeholder: "Search milestones", footer_content: @project.present?, data: { show_no: true, show_any: true, field_name: "milestone_title", selected: params[:milestone_title], project_id: @project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do
+ - if @project
+ %ul.dropdown-footer-list
+ - if can? current_user, :admin_milestone, @project
+ %li
+ = link_to new_namespace_project_milestone_path(@project.namespace, @project), title: "New Milestone" do
+ Create new
+ %li
+ = link_to namespace_project_milestones_path(@project.namespace, @project) do
+ - if can? current_user, :admin_milestone, @project
+ Manage milestones
+ - else
+ View milestones
diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml
index f1d92ef48b2..3fb409ff727 100644
--- a/app/views/shared/issuable/_participants.html.haml
+++ b/app/views/shared/issuable/_participants.html.haml
@@ -1,3 +1,6 @@
+- participants_row = 7
+- participants_size = participants.size
+- participants_extra = participants_size - participants_row
.block.participants
.sidebar-collapsed-icon
= icon('users')
@@ -5,6 +8,13 @@
= participants.count
.title.hide-collapsed
= pluralize participants.count, "participant"
- - participants.each do |participant|
- %span.hide-collapsed
- = link_to_member(@project, participant, name: false, size: 24)
+ .hide-collapsed.participants-list
+ - participants.each do |participant|
+ .participants-author.js-participants-author
+ = link_to_member(@project, participant, name: false, size: 24)
+ - if participants_extra > 0
+ %div.participants-more
+ %a.js-participants-more{href: "#", data: {original_text: "+ #{participants_size - 7} more", less_text: "- show less"}}
+ + #{participants_extra} more
+:javascript
+ Issue.prototype.PARTICIPANTS_ROW_COUNT = #{participants_row};
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 23b1ed1e51b..2b95b19facc 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -1,13 +1,12 @@
%aside.right-sidebar{ class: sidebar_gutter_collapsed_class }
.issuable-sidebar
- .block
+ .block.issuable-sidebar-header
%span.issuable-count.hide-collapsed.pull-left
= issuable.iid
of
= issuables_count(issuable)
- %span.pull-right
- %a.gutter-toggle.js-sidebar-toggle{href: '#'}
- = sidebar_gutter_toggle_icon
+ %a.gutter-toggle.pull-right.js-sidebar-toggle{href: '#'}
+ = sidebar_gutter_toggle_icon
.issuable-nav.hide-collapsed.pull-right.btn-group{role: 'group', "aria-label" => '...'}
- if prev_issuable = prev_issuable_for(issuable)
= link_to 'Prev', [@project.namespace.becomes(Namespace), @project, prev_issuable], class: 'btn btn-default prev-btn'
@@ -22,20 +21,20 @@
= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|
.block.assignee
- .sidebar-collapsed-icon
+ .sidebar-collapsed-icon.sidebar-collapsed-user{data: {toggle: "tooltip", placement: "left", container: "body"}, title: (issuable.assignee.to_reference if issuable.assignee)}
- if issuable.assignee
- = link_to_member_avatar(issuable.assignee, size: 24)
+ = link_to_member(@project, issuable.assignee, size: 24)
- else
= icon('user')
.title.hide-collapsed
- %label
- Assignee
+ Assignee
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
- .pull-right
- = link_to 'Edit', '#', class: 'edit-link'
- .value.hide-collapsed
+ = link_to 'Edit', '#', class: 'edit-link pull-right'
+ .value.bold.hide-collapsed
- if issuable.assignee
- %strong= link_to_member(@project, issuable.assignee, size: 24)
+ = link_to_member(@project, issuable.assignee, size: 32) do
+ %span.username
+ = issuable.assignee.to_reference
- if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee)
%a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'}
= icon('exclamation-triangle')
@@ -54,18 +53,13 @@
- else
No
.title.hide-collapsed
- %label
- Milestone
+ Milestone
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
- .pull-right
- = link_to 'Edit', '#', class: 'edit-link'
- .value.hide-collapsed
+ = link_to 'Edit', '#', class: 'edit-link pull-right'
+ .value.bold.hide-collapsed
- if issuable.milestone
- %span.back-to-milestone
- = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do
- %strong
- = icon('clock-o')
- = issuable.milestone.title
+ = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do
+ = issuable.milestone.title
- else
.light None
.selectbox.hide-collapsed
@@ -80,11 +74,10 @@
%span
= issuable.labels.count
.title.hide-collapsed
- %label Labels
+ Labels
- if can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
- .pull-right
- = link_to 'Edit', '#', class: 'edit-link'
- .value.issuable-show-labels.hide-collapsed
+ = link_to 'Edit', '#', class: 'edit-link pull-right'
+ .value.issuable-show-labels.hide-collapsed{class: ("has-labels" if issuable.labels.any?)}
- if issuable.labels.any?
- issuable.labels.each do |label|
= link_to_label(label, type: issuable.to_ability_name)
@@ -95,14 +88,13 @@
{ selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" }
= render "shared/issuable/participants", participants: issuable.participants(current_user)
- %hr
- if current_user
- subscribed = issuable.subscribed?(current_user)
.block.light.subscription{data: {url: toggle_subscription_path(issuable)}}
.sidebar-collapsed-icon
= icon('rss')
.title.hide-collapsed
- %label.light Notifications
+ Notifications
- subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed'
%button.btn.btn-block.btn-gray.subscribe-button.hide-collapsed{:type => 'button'}
%span= subscribed ? 'Unsubscribe' : 'Subscribe'
diff --git a/app/views/shared/milestones/_issuable.html.haml b/app/views/shared/milestones/_issuable.html.haml
index f7c6fc14adf..85888096722 100644
--- a/app/views/shared/milestones/_issuable.html.haml
+++ b/app/views/shared/milestones/_issuable.html.haml
@@ -10,6 +10,8 @@
%strong #{project.name} &middot;
- elsif show_full_project_name
%strong #{project.name_with_namespace} &middot;
+ - if issuable.is_a?(Issue)
+ = confidential_icon(issuable)
= link_to_gfm issuable.title, [project.namespace.becomes(Namespace), project, issuable], title: issuable.title
%div{class: 'issuable-detail'}
= link_to [project.namespace.becomes(Namespace), project, issuable] do
diff --git a/app/views/shared/milestones/_labels_tab.html.haml b/app/views/shared/milestones/_labels_tab.html.haml
index ba27bafd1bc..868b2357003 100644
--- a/app/views/shared/milestones/_labels_tab.html.haml
+++ b/app/views/shared/milestones/_labels_tab.html.haml
@@ -5,7 +5,7 @@
%li
%span.label-row
= link_to milestones_label_path(options) do
- - render_colored_label(label)
+ - render_colored_label(label, tooltip: false)
%span.prepend-left-10
= markdown(label.description, pipeline: :single_line)
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index f01138af3f0..6b25745c554 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -6,10 +6,10 @@
.col-sm-6
%strong= link_to_gfm truncate(milestone.title, length: 100), milestone_path
.col-sm-6
- .pull-right.light #{milestone.percent_complete}% complete
+ .pull-right.light #{milestone.percent_complete(current_user)}% complete
.row
.col-sm-6
- = link_to pluralize(milestone.issues.size, 'Issue'), issues_path
+ = link_to pluralize(milestone.issues_visible_to_user(current_user).size, 'Issue'), issues_path
&middot;
= link_to pluralize(milestone.merge_requests.size, 'Merge Request'), merge_requests_path
.col-sm-6= milestone_progress_bar(milestone)
diff --git a/app/views/shared/milestones/_summary.html.haml b/app/views/shared/milestones/_summary.html.haml
index 59d4ae29f79..385c6596606 100644
--- a/app/views/shared/milestones/_summary.html.haml
+++ b/app/views/shared/milestones/_summary.html.haml
@@ -3,15 +3,15 @@
.context.prepend-top-default
.milestone-summary
%h4 Progress
- %strong= milestone.issues.size
+ %strong= milestone.issues_visible_to_user(current_user).size
issues:
%span.milestone-stat
- %strong= milestone.issues.opened.size
+ %strong= milestone.issues_visible_to_user(current_user).opened.size
open and
- %strong= milestone.issues.closed.size
+ %strong= milestone.issues_visible_to_user(current_user).closed.size
closed
%span.milestone-stat
- %strong== #{milestone.percent_complete}%
+ %strong== #{milestone.percent_complete(current_user)}%
complete
%span.milestone-stat
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
index 57d7ee85a3b..2b6ce2d7e7a 100644
--- a/app/views/shared/milestones/_tabs.html.haml
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -2,7 +2,7 @@
%li.active
= link_to '#tab-issues', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
Issues
- %span.badge= milestone.issues.size
+ %span.badge= milestone.issues_visible_to_user(current_user).size
%li
= link_to '#tab-merge-requests', 'data-toggle' => 'tab', 'data-show' => '.tab-merge-requests-buttons' do
Merge Requests
@@ -21,7 +21,7 @@
.tab-content.milestone-content
.tab-pane.active#tab-issues
- = render 'shared/milestones/issues_tab', issues: milestone.issues, show_project_name: show_project_name, show_full_project_name: show_full_project_name
+ = render 'shared/milestones/issues_tab', issues: milestone.issues_visible_to_user(current_user), show_project_name: show_project_name, show_full_project_name: show_full_project_name
.tab-pane#tab-merge-requests
= render 'shared/milestones/merge_requests_tab', merge_requests: milestone.merge_requests, show_project_name: show_project_name, show_full_project_name: show_full_project_name
.tab-pane#tab-participants
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index 4cf1d948b5b..cab8743a077 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -28,7 +28,7 @@
%h2.title
= markdown escape_once(milestone.title), pipeline: :single_line
-- if milestone.complete? && milestone.active?
+- if milestone.complete?(current_user) && milestone.active?
.alert.alert-success.prepend-top-default
- close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
%span All issues for this milestone are closed. #{close_msg}
@@ -47,7 +47,7 @@
- project_name = group ? ms.project.name : ms.project.name_with_namespace
= link_to project_name, namespace_project_milestone_path(ms.project.namespace, ms.project, ms)
%td
- = ms.issues.opened.count
+ = ms.issues_visible_to_user(current_user).opened.count
%td
- if ms.closed?
Closed
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 97cfb76cdb0..872d2bdf46d 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -7,26 +7,11 @@
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && project.commit
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- ci_commit = project.ci_commit(project.commit.sha) if ci && !project.empty_repo? && project.commit
-- cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.2']
+- cache_key = [project.namespace, project, controller.controller_name, controller.action_name, current_application_settings, 'v2.3']
- cache_key.push(ci_commit.status) if ci_commit
%li.project-row{ class: css_class }
= cache(cache_key) do
- = link_to project_path(project), class: dom_class(project) do
- - if avatar
- .dash-project-avatar
- - if use_creator_avatar
- = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:''
- - else
- = project_icon(project, alt: '', class: 'avatar project-avatar s40')
- %span.project-full-name.title
- %span.namespace-name
- - if project.namespace && !skip_namespace
- = project.namespace.human_name
- \/
- %span.project-name.filter-title
- = project.name
-
.controls
- if project.main_language
%span
@@ -45,6 +30,23 @@
%span.visibility-icon.has_tooltip{data: { container: 'body', placement: 'left' },
title: "#{visibility_level_label(project.visibility_level)} - #{project_visibility_level_description(project.visibility_level)}"}
= visibility_level_icon(project.visibility_level, fw: false)
+
+ .title
+ = link_to project_path(project), class: dom_class(project) do
+ - if avatar
+ .dash-project-avatar
+ - if use_creator_avatar
+ = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:''
+ - else
+ = project_icon(project, alt: '', class: 'avatar project-avatar s40')
+ %span.project-full-name
+ %span.namespace-name
+ - if project.namespace && !skip_namespace
+ = project.namespace.human_name
+ \/
+ %span.project-name.filter-title
+ = project.name
+
- if show_last_commit_as_description
.description
= link_to_gfm project.commit.title, namespace_project_commit_path(project.namespace, project, project.commit),
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index a316a085107..c96dfefe17f 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -1,8 +1,8 @@
%li.snippet-row
= image_tag avatar_icon(snippet.author_email), class: "avatar s40 hidden-xs", alt: ''
- .snippet-title
- = link_to reliable_snippet_path(snippet), class: 'title' do
+ .title
+ = link_to reliable_snippet_path(snippet) do
= truncate(snippet.title, length: 60)
- if snippet.private?
%span.label.label-gray
diff --git a/app/workers/delete_user_worker.rb b/app/workers/delete_user_worker.rb
new file mode 100644
index 00000000000..6ff361e4d80
--- /dev/null
+++ b/app/workers/delete_user_worker.rb
@@ -0,0 +1,10 @@
+class DeleteUserWorker
+ include Sidekiq::Worker
+
+ def perform(current_user_id, delete_user_id, options = {})
+ delete_user = User.find(delete_user_id)
+ current_user = User.find(current_user_id)
+
+ DeleteUserService.new(current_user).execute(delete_user, options.symbolize_keys)
+ end
+end
diff --git a/app/workers/gitlab_shell_one_shot_worker.rb b/app/workers/gitlab_shell_one_shot_worker.rb
new file mode 100644
index 00000000000..4ddbcf574d5
--- /dev/null
+++ b/app/workers/gitlab_shell_one_shot_worker.rb
@@ -0,0 +1,10 @@
+class GitlabShellOneShotWorker
+ include Sidekiq::Worker
+ include Gitlab::ShellAdapter
+
+ sidekiq_options queue: :gitlab_shell, retry: false
+
+ def perform(action, *arg)
+ gitlab_shell.send(action, *arg)
+ end
+end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 14d7813412e..3cc232ef1ae 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -1,6 +1,5 @@
class PostReceive
include Sidekiq::Worker
- include Gitlab::Identifier
sidekiq_options queue: :post_receive
@@ -11,51 +10,44 @@ class PostReceive
log("Check gitlab.yml config for correct gitlab_shell.repos_path variable. \"#{Gitlab.config.gitlab_shell.repos_path}\" does not match \"#{repo_path}\"")
end
- repo_path.gsub!(/\.git\z/, "")
- repo_path.gsub!(/\A\//, "")
+ post_received = Gitlab::GitPostReceive.new(repo_path, identifier, changes)
- project = Project.find_with_namespace(repo_path)
-
- if project.nil?
+ if post_received.project.nil?
log("Triggered hook for non-existing project with full path \"#{repo_path} \"")
return false
end
- changes = Base64.decode64(changes) unless changes.include?(" ")
- changes = utf8_encode_changes(changes)
- changes = changes.lines
+ if post_received.wiki?
+ # Nothing defined here yet.
+ elsif post_received.regular_project?
+ process_project_changes(post_received)
+ else
+ log("Triggered hook for unidentifiable repository type with full path \"#{repo_path} \"")
+ false
+ end
+ end
- changes.each do |change|
+ def process_project_changes(post_received)
+ post_received.changes.each do |change|
oldrev, newrev, ref = change.strip.split(' ')
- @user ||= identify(identifier, project, newrev)
+ @user ||= post_received.identify(newrev)
unless @user
- log("Triggered hook for non-existing user \"#{identifier} \"")
+ log("Triggered hook for non-existing user \"#{post_received.identifier} \"")
return false
end
if Gitlab::Git.tag_ref?(ref)
- GitTagPushService.new.execute(project, @user, oldrev, newrev, ref)
+ GitTagPushService.new.execute(post_received.project, @user, oldrev, newrev, ref)
else
- GitPushService.new(project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
+ GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
end
end
end
- def utf8_encode_changes(changes)
- changes = changes.dup
-
- changes.force_encoding("UTF-8")
- return changes if changes.valid_encoding?
-
- # Convert non-UTF-8 branch/tag names to UTF-8 so they can be dumped as JSON.
- detection = CharlockHolmes::EncodingDetector.detect(changes)
- return changes unless detection && detection[:encoding]
-
- CharlockHolmes::Converter.convert(changes, detection[:encoding], 'UTF-8')
- end
-
+ private
+
def log(message)
Gitlab::GitLogger.error("POST-RECEIVE: #{message}")
end