Upstream version 8.4.0+dfsg~rc2
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWnhL+AAoJEM4fnGdFEsIqmloP/0HpUbaj7HfM+R02jhLqK9fs lZ0vFBqfpLGM9rQRXqCmGFpYObsmiGZgoWmpIhDBoW/JljXH8pa4C/1En6qHMVC8 l7d+5TqbKekwGaaqKVsP9/T/1lsgcf1vIcQZRa63VvIPYQ9bZKuzaMV8/h9YiIOo qlYfHWt122d6xRj3pQdpNrmEwtniBwiTQbwMm78RbS9kU/AeIlfBSaBuW64c9DHy C1K0L6naYu+4EFquwo9zdpWGF0P+DjfAK0TEOoJK6EBVrurnSbdSjPwTgJaFpXuy SdJc8G5EdOp8nMvPBjDGwfw5UOoPcENhb+Ru6X3Q/ltW8I4qr0OT0JsHPdwPE7db IIpZN/zrSVOEe9tom6QkEWcKvjh3iJA/bDAJT6uQdvV8y8ZwNRx21LEw1C3plAsO lvmH7Pvzel/LjHYPOJfEI+i0AbFTh5NlVj2v66VYsxOCB70M2wKIHX8RsvMtdEYA rt5PiTFABZKb3WjjE+Kvxeue/ETJgBUmOLr+7x4KXOMxdsWuXI3qYL07kmSYTjlG 5kYSorGyQXnaZg27MqFiVplmIT4dXnDIJn7mMYPi79cmTMYMOdVtSkF7CZc03lax 9KOsWNi7DtCuVK6cTuahnkaWAoOZeYu8kODE/FH60tuKSiQWOvijCquRdJ0bE0SV ypBN93pst422K3lb8L10 =mu// -----END PGP SIGNATURE----- Merge tag 'upstream/8.4.0+dfsg_rc2' Upstream version 8.4.0+dfsg~rc2 # gpg: Signature made Tuesday 19 January 2016 04:12:06 PM IST using RSA key ID 4512C22A # gpg: Good signature from "Praveen Arimbrathodiyil (piratepin) <praveen@debian.org>" # gpg: aka "Pirate Praveen (pirates.org.in) <praveen@onenetbeyond.org>" # gpg: aka "Pirate Praveen (piratesin) <me@j4v4m4n.in>" # gpg: aka "Pirate Praveen (PP) <praveen@privacyrequired.com>" # gpg: aka "Praveen Arimbrathodiyil (j4v4m4n) <pravi.a@gmail.com>"
This commit is contained in:
commit
94edbca68b
341 changed files with 5861 additions and 1687 deletions
20
CHANGELOG
20
CHANGELOG
|
@ -1,6 +1,9 @@
|
|||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.4.0 (unreleased)
|
||||
- Add pagination headers to already paginated API resources
|
||||
- Properly generate diff of orphan commits, like the first commit in a repository
|
||||
- Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages
|
||||
- Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse)
|
||||
- Improved performance of finding issues for an entire group (Yorick Peterse)
|
||||
- Added custom application performance measuring system powered by InfluxDB (Yorick Peterse)
|
||||
|
@ -13,8 +16,11 @@ v 8.4.0 (unreleased)
|
|||
- Fix missing date of month in network graph when commits span a month (Stan Hu)
|
||||
- Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu)
|
||||
- Don't notify users twice if they are both project watchers and subscribers (Stan Hu)
|
||||
- Remove gray background from layout in UI
|
||||
- Fix signup for OAuth providers that don't provide a name
|
||||
- Implement new UI for group page
|
||||
- Implement search inside emoji picker
|
||||
- Let the CI runner know about builds that this build depends on
|
||||
- Add API support for looking up a user by username (Stan Hu)
|
||||
- Add project permissions to all project API endpoints (Stan Hu)
|
||||
- Link to milestone in "Milestone changed" system note
|
||||
|
@ -42,9 +48,20 @@ v 8.4.0 (unreleased)
|
|||
- Ajax filter by message for commits page
|
||||
- API: Add support for deleting a tag via the API (Robert Schilling)
|
||||
- Allow subsequent validations in CI Linter
|
||||
- Show referenced MRs & Issues only when the current viewer can access them
|
||||
- Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee)
|
||||
- Add API support for managing project's builds
|
||||
- Add API support for managing project's build triggers
|
||||
- Add API support for managing project's build variables
|
||||
- Allow broadcast messages to be edited
|
||||
- Autosize Markdown textareas
|
||||
- Import GitHub wiki into GitLab
|
||||
- Add reporters ability to download and browse build artifacts (Andrew Johnson)
|
||||
- Autofill referring url in message box when reporting user abuse. (Josh Frye)
|
||||
|
||||
v 8.3.4
|
||||
- Use gitlab-workhorse 0.5.4 (fixes API routing bug)
|
||||
- Add build artifacts browser
|
||||
|
||||
v 8.3.3
|
||||
- Preserve CE behavior with JIRA integration by only calling API if URL is set
|
||||
|
@ -59,6 +76,8 @@ v 8.3.3
|
|||
- Fix Error 500 when visiting build page of project with nil runners_token (Stan Hu)
|
||||
- Use WOFF versions of SourceSansPro fonts
|
||||
- Fix regression when builds were not generated for tags created through web/api interface
|
||||
- Fix: maintain milestone filter between Open and Closed tabs (Greg Smethells)
|
||||
- Fix missing artifacts and build traces for build created before 8.3
|
||||
|
||||
v 8.3.2
|
||||
- Disable --follow in `git log` to avoid loading duplicate commit data in infinite scroll (Stan Hu)
|
||||
|
@ -76,6 +95,7 @@ v 8.3.0
|
|||
- Add open_issues_count to project API (Stan Hu)
|
||||
- Expand character set of usernames created by Omniauth (Corey Hinshaw)
|
||||
- Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
|
||||
- Add unsubscribe link in the email footer (Zeger-Jan van de Weg)
|
||||
- Provide better diagnostic message upon project creation errors (Stan Hu)
|
||||
- Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu)
|
||||
- Remove api credentials from link to build_page
|
||||
|
|
|
@ -334,9 +334,9 @@ merge request:
|
|||
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript)
|
||||
1. [Shell commands](doc/development/shell_commands.md) created by GitLab
|
||||
contributors to enhance security
|
||||
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
|
||||
1. [Database Migrations](doc/development/migration_style_guide.md)
|
||||
1. [Documentation styleguide](doc_styleguide.md)
|
||||
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
|
||||
1. [Documentation styleguide](doc/development/doc_styleguide.md)
|
||||
1. Interface text should be written subjectively instead of objectively. It
|
||||
should be the GitLab core team addressing a person. It should be written in
|
||||
present time and never use past tense (has been/was). For example instead
|
||||
|
|
4
Procfile
4
Procfile
|
@ -2,6 +2,6 @@
|
|||
# https://gitlab.com/gitlab-org/omnibus-gitlab or the init scripts in
|
||||
# lib/support/init.d, which call scripts in bin/ .
|
||||
#
|
||||
web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"}
|
||||
worker: bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default
|
||||
web: RAILS_ENV=development bin/web start_foreground
|
||||
worker: RAILS_ENV=development bin/background_jobs start_foreground
|
||||
# mail_room: bundle exec mail_room -q -c config/mail_room.yml
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.4.0.rc1
|
||||
8.4.0-rc2
|
BIN
app/assets/fonts/SourceSansPro-Black.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-Black.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-BlackIt.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-Bold.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-Bold.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-BoldIt.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-ExtraLight.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-ExtraLightIt.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-It.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-It.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-Light.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-Light.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-LightIt.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-LightIt.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-Regular.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-Regular.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-Semibold.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-Semibold.ttf.woff2
Executable file
Binary file not shown.
BIN
app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2
Executable file
BIN
app/assets/fonts/SourceSansPro-SemiboldIt.ttf.woff2
Executable file
Binary file not shown.
|
@ -1,7 +1,7 @@
|
|||
class @Activities
|
||||
constructor: ->
|
||||
Pager.init 20, true
|
||||
$(".event-filter .btn").bind "click", (event) =>
|
||||
$(".event-filter a").bind "click", (event) =>
|
||||
event.preventDefault()
|
||||
@toggleFilter($(event.currentTarget))
|
||||
@reloadActivities()
|
||||
|
@ -12,7 +12,7 @@ class @Activities
|
|||
|
||||
|
||||
toggleFilter: (sender) ->
|
||||
sender.toggleClass "active"
|
||||
sender.closest('li').toggleClass "active"
|
||||
event_filters = $.cookie("event_filter")
|
||||
filter = sender.attr("id").split("_")[0]
|
||||
if event_filters
|
||||
|
|
|
@ -10,19 +10,19 @@ class @Admin
|
|||
|
||||
$('body').on 'click', '.js-toggle-colors-link', (e) ->
|
||||
e.preventDefault()
|
||||
$('.js-toggle-colors-link').hide()
|
||||
$('.js-toggle-colors-container').show()
|
||||
$('.js-toggle-colors-container').toggle()
|
||||
|
||||
$('input#broadcast_message_color').on 'input', ->
|
||||
previewColor = $('input#broadcast_message_color').val()
|
||||
previewColor = $(@).val()
|
||||
$('div.broadcast-message-preview').css('background-color', previewColor)
|
||||
|
||||
$('input#broadcast_message_font').on 'input', ->
|
||||
previewColor = $('input#broadcast_message_font').val()
|
||||
previewColor = $(@).val()
|
||||
$('div.broadcast-message-preview').css('color', previewColor)
|
||||
|
||||
$('textarea#broadcast_message_message').on 'input', ->
|
||||
previewMessage = $('textarea#broadcast_message_message').val()
|
||||
previewMessage = $(@).val()
|
||||
previewMessage = "Your message here" if previewMessage.trim() == ''
|
||||
$('div.broadcast-message-preview span').text(previewMessage)
|
||||
|
||||
$('.log-tabs a').click (e) ->
|
||||
|
|
|
@ -5,7 +5,7 @@ class @AwardsHandler
|
|||
event.preventDefault()
|
||||
$(".emoji-menu").show()
|
||||
|
||||
$("html").click ->
|
||||
$("html").on 'click', (event) ->
|
||||
if !$(event.target).closest(".emoji-menu").length
|
||||
if $(".emoji-menu").is(":visible")
|
||||
$(".emoji-menu").hide()
|
||||
|
|
4
app/assets/javascripts/behaviors/autosize.js.coffee
Normal file
4
app/assets/javascripts/behaviors/autosize.js.coffee
Normal file
|
@ -0,0 +1,4 @@
|
|||
#= require autosize
|
||||
|
||||
$ ->
|
||||
autosize($('.js-autosize'))
|
|
@ -6,11 +6,25 @@ class @Issue
|
|||
constructor: ->
|
||||
# Prevent duplicate event bindings
|
||||
@disableTaskList()
|
||||
|
||||
@fixAffixScroll()
|
||||
if $('a.btn-close').length
|
||||
@initTaskList()
|
||||
@initIssueBtnEventListeners()
|
||||
|
||||
fixAffixScroll: ->
|
||||
fixAffix = ->
|
||||
$discussion = $('.issuable-discussion')
|
||||
$sidebar = $('.issuable-sidebar')
|
||||
if $sidebar.hasClass('no-affix')
|
||||
$sidebar.removeClass(['affix-top','affix'])
|
||||
discussionHeight = $discussion.height()
|
||||
sidebarHeight = $sidebar.height()
|
||||
if sidebarHeight > discussionHeight
|
||||
$discussion.height(sidebarHeight + 50)
|
||||
$sidebar.addClass('no-affix')
|
||||
$(window).on('resize', fixAffix)
|
||||
fixAffix()
|
||||
|
||||
initTaskList: ->
|
||||
$('.detail-page-description .js-task-list-container').taskList('enable')
|
||||
$(document).on 'tasklist:changed', '.detail-page-description .js-task-list-container', @updateTaskList
|
||||
|
|
|
@ -15,6 +15,8 @@ class @MergeRequest
|
|||
this.$('.show-all-commits').on 'click', =>
|
||||
this.showAllCommits()
|
||||
|
||||
@fixAffixScroll();
|
||||
|
||||
@initTabs()
|
||||
|
||||
# Prevent duplicate event bindings
|
||||
|
@ -28,6 +30,20 @@ class @MergeRequest
|
|||
$: (selector) ->
|
||||
this.$el.find(selector)
|
||||
|
||||
fixAffixScroll: ->
|
||||
fixAffix = ->
|
||||
$discussion = $('.issuable-discussion')
|
||||
$sidebar = $('.issuable-sidebar')
|
||||
if $sidebar.hasClass('no-affix')
|
||||
$sidebar.removeClass(['affix-top','affix'])
|
||||
discussionHeight = $discussion.height()
|
||||
sidebarHeight = $sidebar.height()
|
||||
if sidebarHeight > discussionHeight
|
||||
$discussion.height(sidebarHeight + 50)
|
||||
$sidebar.addClass('no-affix')
|
||||
$(window).on('resize', fixAffix)
|
||||
fixAffix()
|
||||
|
||||
initTabs: ->
|
||||
if @opts.action != 'new'
|
||||
# `MergeRequests#new` has no tab-persisting or lazy-loading behavior
|
||||
|
@ -48,14 +64,15 @@ class @MergeRequest
|
|||
_this = @
|
||||
$('a.btn-close, a.btn-reopen').on 'click', (e) ->
|
||||
$this = $(this)
|
||||
if $this.data('submitted')
|
||||
return
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
shouldSubmit = $this.hasClass('btn-comment')
|
||||
console.log("shouldSubmit")
|
||||
if shouldSubmit && $this.data('submitted')
|
||||
return
|
||||
if shouldSubmit
|
||||
_this.submitNoteForm($this.closest('form'),$this)
|
||||
if $this.hasClass('btn-comment-and-close') || $this.hasClass('btn-comment-and-reopen')
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
_this.submitNoteForm($this.closest('form'),$this)
|
||||
|
||||
|
||||
submitNoteForm: (form, $button) =>
|
||||
noteText = form.find("textarea.js-note-text").val()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#
|
||||
# ### Example Markup
|
||||
#
|
||||
# <ul class="nav nav-tabs merge-request-tabs">
|
||||
# <ul class="nav-links merge-request-tabs">
|
||||
# <li class="notes-tab active">
|
||||
# <a data-action="notes" data-target="#notes" data-toggle="tab" href="/foo/bar/merge_requests/1">
|
||||
# Discussion
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#= require autosave
|
||||
#= require autosize
|
||||
#= require dropzone
|
||||
#= require dropzone_input
|
||||
#= require gfm_auto_complete
|
||||
|
@ -246,6 +247,7 @@ class @Notes
|
|||
else
|
||||
previewButton.removeClass("turn-on").addClass "turn-off"
|
||||
|
||||
autosize(textarea)
|
||||
new Autosave textarea, [
|
||||
"Note"
|
||||
form.find("#note_commit_id").val()
|
||||
|
@ -353,7 +355,7 @@ class @Notes
|
|||
$('.note[id="' + note_id + '"]').each ->
|
||||
note = $(this)
|
||||
notes = note.closest(".notes")
|
||||
count = notes.closest(".notes_holder").find(".discussion-notes-count")
|
||||
count = notes.closest(".issuable-details").find(".notes-tab .badge")
|
||||
|
||||
# check if this is the last note for this line
|
||||
if notes.find(".note").length is 1
|
||||
|
@ -363,9 +365,10 @@ class @Notes
|
|||
|
||||
# for diff lines
|
||||
notes.closest("tr").remove()
|
||||
else
|
||||
# update notes count
|
||||
count.get(0).lastChild.nodeValue = " #{notes.children().length - 1}"
|
||||
|
||||
# update notes count
|
||||
oldNum = parseInt(count.text())
|
||||
count.text(oldNum - 1)
|
||||
|
||||
note.remove()
|
||||
|
||||
|
@ -521,9 +524,13 @@ class @Notes
|
|||
if textarea.val().trim().length > 0
|
||||
form.find('.js-note-target-reopen').text('Comment & reopen')
|
||||
form.find('.js-note-target-close').text('Comment & close')
|
||||
form.find('.js-note-target-reopen').addClass('btn-comment-and-reopen')
|
||||
form.find('.js-note-target-close').addClass('btn-comment-and-close')
|
||||
else
|
||||
form.find('.js-note-target-reopen').text('Reopen')
|
||||
form.find('.js-note-target-close').text('Close')
|
||||
form.find('.js-note-target-reopen').removeClass('btn-comment-and-reopen')
|
||||
form.find('.js-note-target-close').removeClass('btn-comment-and-close')
|
||||
|
||||
initTaskList: ->
|
||||
@enableTaskList()
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
#= require latinise
|
||||
|
||||
class @Wikis
|
||||
constructor: ->
|
||||
$('.build-new-wiki').bind "click", (e) ->
|
||||
$('[data-error~=slug]').addClass("hidden")
|
||||
$('p.hint').show()
|
||||
$('.build-new-wiki').bind 'click', (e) =>
|
||||
$('[data-error~=slug]').addClass('hidden')
|
||||
field = $('#new_wiki_path')
|
||||
valid_slug_pattern = /^[\w\/-]+$/
|
||||
slug = @slugify(field.val())
|
||||
|
||||
slug = field.val()
|
||||
if slug.match valid_slug_pattern
|
||||
if (slug.length > 0)
|
||||
path = field.attr('data-wikis-path')
|
||||
if(slug.length > 0)
|
||||
location.href = path + "/" + slug
|
||||
else
|
||||
e.preventDefault()
|
||||
$('p.hint').hide()
|
||||
$('[data-error~=slug]').removeClass("hidden")
|
||||
location.href = path + '/' + slug
|
||||
|
||||
dasherize: (value) ->
|
||||
value.replace(/[_\s]+/g, '-')
|
||||
|
||||
slugify: (value) =>
|
||||
@dasherize(value.trim().toLowerCase().latinise())
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
@import "framework/lists.scss";
|
||||
@import "framework/markdown_area.scss";
|
||||
@import "framework/mobile.scss";
|
||||
@import "framework/nav.scss";
|
||||
@import "framework/pagination.scss";
|
||||
@import "framework/panels.scss";
|
||||
@import "framework/selects.scss";
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
line-height: 36px;
|
||||
}
|
||||
|
||||
.content-block,
|
||||
.gray-content-block {
|
||||
margin: -$gl-padding;
|
||||
margin-top: 0;
|
||||
margin-bottom: -$gl-padding;
|
||||
background-color: $background-color;
|
||||
padding: $gl-padding;
|
||||
margin-bottom: 0px;
|
||||
|
@ -86,10 +86,7 @@
|
|||
.cover-block {
|
||||
text-align: center;
|
||||
background: $background-color;
|
||||
margin: -$gl-padding;
|
||||
margin-bottom: 0;
|
||||
padding: 44px $gl-padding;
|
||||
border-bottom: 1px solid $border-color;
|
||||
padding-top: 44px;
|
||||
position: relative;
|
||||
|
||||
.avatar-holder {
|
||||
|
@ -136,3 +133,19 @@
|
|||
.block-connector {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.nav-block {
|
||||
.controls {
|
||||
float: right;
|
||||
margin-top: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding: $gl-padding 0;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
&.oneline-block {
|
||||
line-height: 42px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
@mixin btn-default {
|
||||
@include border-radius(3px);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-size: 15px;
|
||||
font-size: $gl-font-size;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
padding: 11px $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
|
@ -17,8 +13,6 @@
|
|||
|
||||
@mixin btn-middle {
|
||||
@include btn-default;
|
||||
@include border-radius(3px);
|
||||
padding: 11px 24px;
|
||||
}
|
||||
|
||||
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
|
||||
|
@ -74,16 +68,15 @@
|
|||
@include btn-default;
|
||||
@include btn-white;
|
||||
|
||||
&.btn-small,
|
||||
&.btn-sm {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
&.btn-nr {
|
||||
padding: 7px 10px;
|
||||
padding: 4px 10px;
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
&.btn-xs {
|
||||
padding: 1px 5px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
&.btn-success,
|
||||
|
@ -131,6 +124,12 @@
|
|||
&:last-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
&.btn-xs {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
&.disabled {
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,33 +152,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
.btn-group-next {
|
||||
.btn {
|
||||
padding: 9px 0px;
|
||||
font-size: 15px;
|
||||
color: #7f8fa4;
|
||||
border-color: #e7e9ed;
|
||||
width: 140px;
|
||||
|
||||
.badge {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
color: #78a;
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: $gl-info;
|
||||
background: $gl-info;
|
||||
color: #fff;
|
||||
|
||||
.badge {
|
||||
color: $gl-info;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
border: none;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.input-group-btn {
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
@include btn-middle;
|
||||
|
||||
&:hover {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.btn-clipboard {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
|
||||
|
||||
border: 1px solid #c6cacf !important;
|
||||
background-color: #e4e7ed !important;
|
||||
}
|
||||
|
||||
.btn-green {
|
||||
@include btn-green
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ hr {
|
|||
@include str-truncated;
|
||||
}
|
||||
|
||||
.item-title { font-weight: 600; }
|
||||
|
||||
/** FLASH message **/
|
||||
.author_link {
|
||||
color: $gl-link-color;
|
||||
|
@ -374,75 +376,6 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
.center-top-menu, .left-top-menu {
|
||||
@include nav-menu;
|
||||
text-align: center;
|
||||
margin-top: 5px;
|
||||
margin-bottom: $gl-padding;
|
||||
height: auto;
|
||||
margin-top: -$gl-padding;
|
||||
|
||||
&.no-bottom {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&.no-top {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
li a {
|
||||
display: inline-block;
|
||||
padding-top: $gl-padding;
|
||||
padding-bottom: 11px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
&.bottom-border {
|
||||
border-bottom: 1px solid $border-color;
|
||||
height: 57px;
|
||||
}
|
||||
|
||||
&.wide {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.left-top-menu {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #EEE;
|
||||
}
|
||||
|
||||
.center-middle-menu {
|
||||
@include nav-menu;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
margin: -$gl-padding;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
height: 58px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
li {
|
||||
&:after {
|
||||
content: "|";
|
||||
color: $border-gray-light;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropzone .dz-preview .dz-progress {
|
||||
border-color: $border-color !important;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,8 @@
|
|||
*
|
||||
*/
|
||||
.file-holder {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
border: none;
|
||||
border-top: 1px solid #E7E9EE;
|
||||
border-bottom: 1px solid #E7E9EE;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
&.readme-holder {
|
||||
border-bottom: 0;
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
.flash-notice {
|
||||
@extend .alert;
|
||||
@extend .alert-info;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.flash-alert {
|
||||
@extend .alert;
|
||||
@extend .alert-danger;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,23 +3,39 @@
|
|||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), font-url('SourceSansPro-Light.ttf.woff');
|
||||
src:
|
||||
local('Source Sans Pro Light'),
|
||||
local('SourceSansPro-Light'),
|
||||
font-url('SourceSansPro-Light.ttf.woff2') format('woff2'),
|
||||
font-url('SourceSansPro-Light.ttf.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Source Sans Pro'), local('SourceSansPro-Regular'), font-url('SourceSansPro-Regular.ttf.woff');
|
||||
src:
|
||||
local('Source Sans Pro'),
|
||||
local('SourceSansPro-Regular'),
|
||||
font-url('SourceSansPro-Regular.ttf.woff2') format('woff2'),
|
||||
font-url('SourceSansPro-Regular.ttf.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), font-url('SourceSansPro-Semibold.ttf.woff');
|
||||
src:
|
||||
local('Source Sans Pro Semibold'),
|
||||
local('SourceSansPro-Semibold'),
|
||||
font-url('SourceSansPro-Semibold.ttf.woff2') format('woff2'),
|
||||
font-url('SourceSansPro-Semibold.ttf.woff') format('woff');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Source Sans Pro';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), font-url('SourceSansPro-Bold.ttf.woff');
|
||||
src:
|
||||
local('Source Sans Pro Bold'),
|
||||
local('SourceSansPro-Bold'),
|
||||
font-url('SourceSansPro-Bold.ttf.woff2') format('woff2'),
|
||||
font-url('SourceSansPro-Bold.ttf.woff') format('woff');
|
||||
}
|
||||
|
|
|
@ -74,8 +74,10 @@ label {
|
|||
|
||||
.form-control {
|
||||
@include box-shadow(none);
|
||||
height: 42px;
|
||||
padding: 8px $gl-padding;
|
||||
}
|
||||
|
||||
.form-control-inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.wiki-content {
|
||||
|
|
|
@ -28,6 +28,7 @@ header {
|
|||
min-height: $header-height;
|
||||
background-color: #fff;
|
||||
border: none;
|
||||
border-bottom: 1px solid #EEE;
|
||||
|
||||
.container-fluid {
|
||||
width: 100% !important;
|
||||
|
|
|
@ -5,8 +5,6 @@ html {
|
|||
}
|
||||
|
||||
body {
|
||||
background-color: #F3F3F3 !important;
|
||||
|
||||
&.navless {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
|
|
@ -109,10 +109,8 @@ ul.content-list {
|
|||
padding: 0;
|
||||
|
||||
> li {
|
||||
padding: $gl-padding;
|
||||
padding: $gl-padding 0;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
color: $gl-gray;
|
||||
|
||||
.avatar {
|
||||
|
@ -133,6 +131,7 @@ ul.content-list {
|
|||
.panel > .content-list {
|
||||
li {
|
||||
margin: 0;
|
||||
padding: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +147,7 @@ ul.controls {
|
|||
> li {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
|
|
@ -65,13 +65,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.md-header {
|
||||
ul {
|
||||
float: left;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.referenced-users {
|
||||
color: #4c4e54;
|
||||
padding-top: 10px;
|
||||
|
@ -85,28 +78,12 @@
|
|||
box-shadow: none;
|
||||
}
|
||||
|
||||
.new_note,
|
||||
.edit_note,
|
||||
.detail-page-description,
|
||||
.milestone-description,
|
||||
.wiki-content,
|
||||
.merge-request-form {
|
||||
.nav-tabs {
|
||||
margin-bottom: 0;
|
||||
border: none;
|
||||
|
||||
li a,
|
||||
li.active a {
|
||||
border: 1px solid #DDD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.markdown-area {
|
||||
@include border-radius(0);
|
||||
background: #FFF;
|
||||
border: 1px solid #ddd;
|
||||
min-height: 140px;
|
||||
max-height: 430px;
|
||||
padding: 5px;
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
|
|
|
@ -118,38 +118,3 @@
|
|||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
@mixin nav-menu {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
height: 56px;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
|
||||
a {
|
||||
padding: 14px;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
color: #959494;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.active a {
|
||||
color: #616060;
|
||||
border-bottom: 2px solid #4688f1;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
color: #78a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.nav.nav-tabs > li > a {
|
||||
.nav-links > li > a {
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
margin-right: 3px;
|
||||
|
@ -81,7 +81,7 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.center-top-menu, .left-top-menu {
|
||||
.nav-links, .nav-links {
|
||||
li a {
|
||||
font-size: 14px;
|
||||
padding: 19px 10px;
|
||||
|
@ -100,11 +100,6 @@
|
|||
}
|
||||
|
||||
@media (max-width: $screen-sm-max) {
|
||||
.page-with-sidebar .content-wrapper {
|
||||
padding: 0;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
.issues-filters {
|
||||
.milestone-filter, .labels-filter {
|
||||
display: none;
|
||||
|
|
39
app/assets/stylesheets/framework/nav.scss
Normal file
39
app/assets/stylesheets/framework/nav.scss
Normal file
|
@ -0,0 +1,39 @@
|
|||
.nav-links {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
height: auto;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
padding: 14px;
|
||||
padding-top: $gl-padding;
|
||||
padding-bottom: 11px;
|
||||
margin-bottom: -1px;
|
||||
font-size: 15px;
|
||||
line-height: 28px;
|
||||
color: #959494;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.active a {
|
||||
color: #000000;
|
||||
border-bottom: 2px solid #4688f1;
|
||||
}
|
||||
|
||||
.badge {
|
||||
font-weight: normal;
|
||||
background-color: #eee;
|
||||
color: #78a;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@
|
|||
.select2-choice {
|
||||
background: #FFF;
|
||||
border-color: #DDD;
|
||||
height: 42px;
|
||||
padding: 8px $gl-padding;
|
||||
height: 36px;
|
||||
padding: 6px $gl-padding;
|
||||
font-size: $gl-font-size;
|
||||
line-height: 1.42857143;
|
||||
|
||||
|
|
|
@ -21,11 +21,10 @@
|
|||
|
||||
.content-wrapper {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
|
||||
.container-fluid {
|
||||
background: #FFF;
|
||||
padding: $gl-padding;
|
||||
padding: 0 $gl-padding;
|
||||
|
||||
&.container-blank {
|
||||
background: none;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
.table-holder {
|
||||
margin: -$gl-padding;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
&.table {
|
||||
margin-bottom: $gl-padding;
|
||||
|
||||
|
||||
.dropdown-menu a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -32,6 +30,7 @@ table {
|
|||
}
|
||||
|
||||
th {
|
||||
background-color: $background-color;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
border-bottom: 1px solid $border-color !important;
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
padding: 0;
|
||||
|
||||
.timeline-entry {
|
||||
padding: $gl-padding;
|
||||
padding: $gl-padding 0;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
color: $gl-gray;
|
||||
border-bottom: 1px solid $border-white-light;
|
||||
|
||||
|
|
|
@ -99,47 +99,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Nav tabs
|
||||
.nav.nav-tabs {
|
||||
margin-bottom: 15px;
|
||||
|
||||
li {
|
||||
> a {
|
||||
margin-right: 5px;
|
||||
line-height: 20px;
|
||||
border-color: #EEE;
|
||||
color: #888;
|
||||
border-bottom: 1px solid #ddd;
|
||||
.badge {
|
||||
background-color: #eee;
|
||||
color: #888;
|
||||
text-shadow: 0 1px 1px #fff;
|
||||
}
|
||||
i.fa {
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
> a {
|
||||
border-color: #CCC;
|
||||
border-bottom: 1px solid #fff;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-tabs > li > a,
|
||||
.nav-pills > li > a {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.nav-pills > .active > a > span > .badge {
|
||||
background-color: #fff;
|
||||
color: $gl-primary;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* fix to keep tooltips position in top navigation bar
|
||||
|
|
|
@ -46,7 +46,7 @@ $font-size-base: $gl-font-size;
|
|||
//
|
||||
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
|
||||
|
||||
$padding-base-vertical: 9px;
|
||||
$padding-base-vertical: $gl-vert-padding;
|
||||
$padding-base-horizontal: $gl-padding;
|
||||
$component-active-color: #fff;
|
||||
$component-active-bg: $brand-info;
|
||||
|
|
|
@ -177,7 +177,7 @@ body {
|
|||
}
|
||||
|
||||
.page-title {
|
||||
margin-top: 0px;
|
||||
margin-top: $gl-padding;
|
||||
line-height: 1.3;
|
||||
font-size: 1.25em;
|
||||
font-weight: 600;
|
||||
|
|
|
@ -22,6 +22,7 @@ $header-height: 58px;
|
|||
$fixed-layout-width: 1280px;
|
||||
$gl-gray: #5a5a5a;
|
||||
$gl-padding: 16px;
|
||||
$gl-vert-padding: 6px;
|
||||
$gl-padding-top:10px;
|
||||
$gl-avatar-size: 46px;
|
||||
$secondary-text: #7f8fa4;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
position: absolute;
|
||||
top: 0px;
|
||||
right: 4px;
|
||||
line-height: 40px;
|
||||
line-height: 56px;
|
||||
}
|
||||
|
||||
a.js-zen-leave {
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
}
|
||||
|
||||
.commit-box {
|
||||
border-top: 1px solid $border-color;
|
||||
|
||||
.commit-title {
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
.detail-page-header {
|
||||
margin: -$gl-padding;
|
||||
padding: 7px $gl-padding;
|
||||
margin-bottom: 0px;
|
||||
padding: 11px 0;
|
||||
border-bottom: 1px solid $border-color;
|
||||
color: #5c5d5e;
|
||||
font-size: 16px;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
// Common
|
||||
.diff-file {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
border: none;
|
||||
border-bottom: 1px solid #E7E9EE;
|
||||
border: 1px solid $border-color;
|
||||
border-top: none;
|
||||
|
||||
.diff-header {
|
||||
position: relative;
|
||||
|
@ -23,14 +21,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.diff-controls {
|
||||
.btn {
|
||||
padding: 0px 10px;
|
||||
font-size: 13px;
|
||||
line-height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.commit-short-id {
|
||||
font-family: $monospace_font;
|
||||
font-size: smaller;
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
*/
|
||||
.event-item {
|
||||
font-size: $gl-font-size;
|
||||
padding: $gl-padding $gl-padding $gl-padding ($gl-padding + $gl-avatar-size + 15px);
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
padding: $gl-padding 0 $gl-padding ($gl-avatar-size + 15px);
|
||||
border-bottom: 1px solid $table-border-color;
|
||||
color: #7f8fa4;
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
position: fixed;
|
||||
top: 70px;
|
||||
margin-right: 35px;
|
||||
|
||||
&.no-affix {
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,10 +32,10 @@
|
|||
.project-issuable-filter {
|
||||
.controls {
|
||||
float: right;
|
||||
margin-top: 7px;
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
||||
.center-top-menu {
|
||||
.nav-links {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +100,7 @@
|
|||
|
||||
.cross-project-reference {
|
||||
color: $gl-link-color;
|
||||
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
width: 85%;
|
||||
|
@ -105,8 +110,13 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
cite {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
button {
|
||||
float: right;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
.issue-title {
|
||||
margin-bottom: 5px;
|
||||
font-size: $list-font-size;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.issue-info {
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
*
|
||||
*/
|
||||
.mr-state-widget {
|
||||
background: #F7F8FA;
|
||||
background: $background-color;
|
||||
color: $gl-gray;
|
||||
border: 1px solid #dce0e6;
|
||||
border: 1px solid $border-color;
|
||||
@include border-radius(2px);
|
||||
|
||||
form {
|
||||
|
@ -150,7 +150,7 @@
|
|||
.merge-request-title {
|
||||
margin-bottom: 5px;
|
||||
font-size: $list-font-size;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.merge-request-info {
|
||||
|
|
|
@ -159,6 +159,7 @@
|
|||
.edit_note {
|
||||
.markdown-area {
|
||||
min-height: 140px;
|
||||
max-height: 430px;
|
||||
}
|
||||
.note-form-actions {
|
||||
background: transparent;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
}
|
||||
|
||||
.project-home-panel {
|
||||
padding-bottom: 40px;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.cover-controls {
|
||||
.project-settings-dropdown {
|
||||
|
@ -51,6 +53,8 @@
|
|||
}
|
||||
|
||||
.notifications-btn {
|
||||
margin-top: -28px;
|
||||
|
||||
.fa-bell {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
@ -75,17 +79,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.git-clone-holder {
|
||||
max-width: 498px;
|
||||
|
||||
.form-control {
|
||||
background: #FFF;
|
||||
font-size: 14px;
|
||||
height: 42px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.visibility-level-label {
|
||||
@extend .btn;
|
||||
@extend .btn-gray;
|
||||
|
@ -98,11 +91,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.git-clone-holder {
|
||||
display: inline-table;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.project-repo-buttons {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 0px;
|
||||
|
@ -112,10 +100,22 @@
|
|||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.clone-row {
|
||||
.split-repo-buttons,
|
||||
.project-clone-holder {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.split-repo-buttons {
|
||||
margin: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.count-with-arrow {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
@ -160,8 +160,8 @@
|
|||
border-style: solid;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
padding: 11px 16px;
|
||||
line-height: 13px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
|
@ -189,117 +189,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.git-clone-holder {
|
||||
.project-home-dropdown + & {
|
||||
margin-right: 45px;
|
||||
}
|
||||
|
||||
.clone-options {
|
||||
display: table-cell;
|
||||
a.btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
cursor: auto;
|
||||
@extend .monospace;
|
||||
background: #FAFAFA;
|
||||
width: 101%;
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
background: #f7f8fa;
|
||||
|
||||
&.git-protocols {
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
.input-group-btn:last-child > .btn {
|
||||
@include border-radius-right(0);
|
||||
|
||||
border-left: 1px solid #c6cacf;
|
||||
margin-left: -2px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.projects-search-form {
|
||||
|
||||
.input-group .form-control {
|
||||
height: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-btn {
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
@include btn-middle;
|
||||
|
||||
&:hover {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.btn-clipboard {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
|
||||
|
||||
border: 1px solid #c6cacf !important;
|
||||
background-color: #e4e7ed !important;
|
||||
}
|
||||
|
||||
.btn-green {
|
||||
@include btn-green
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.split-repo-buttons {
|
||||
display: inline-table;
|
||||
margin: 0 12px 0 12px;
|
||||
|
||||
.btn{
|
||||
@include btn-gray;
|
||||
@include btn-default;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
margin: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
#notification-form {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.dropdown-new {
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
.open > .dropdown-new.btn {
|
||||
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
|
||||
|
||||
border: 1px solid #c6cacf !important;
|
||||
background-color: #e4e7ed !important;
|
||||
text-transform: none;
|
||||
color: #313236 !important;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
|
||||
@include border-radius (0px);
|
||||
|
@ -351,28 +240,6 @@
|
|||
color: #555;
|
||||
}
|
||||
|
||||
ul.nav.nav-projects-tabs {
|
||||
@extend .nav-tabs;
|
||||
|
||||
padding-left: 8px;
|
||||
|
||||
li {
|
||||
a {
|
||||
padding: 6px 25px;
|
||||
margin-top: 2px;
|
||||
border-color: #DDD;
|
||||
background-color: #EEE;
|
||||
text-shadow: 0 1px 1px white;
|
||||
color: #555;
|
||||
}
|
||||
&.active {
|
||||
a {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project_member_row form {
|
||||
margin: 0px;
|
||||
}
|
||||
|
@ -399,9 +266,9 @@ ul.nav.nav-projects-tabs {
|
|||
|
||||
.breadcrumb.repo-breadcrumb {
|
||||
padding: 0;
|
||||
line-height: 42px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
line-height: 42px;
|
||||
margin: 0;
|
||||
|
||||
> li + li:before {
|
||||
|
@ -416,11 +283,8 @@ ul.nav.nav-projects-tabs {
|
|||
|
||||
.top-area {
|
||||
border-bottom: 1px solid #EEE;
|
||||
margin: 0 -16px;
|
||||
padding: 0 $gl-padding;
|
||||
height: 42px;
|
||||
|
||||
ul.left-top-menu {
|
||||
ul.nav-links {
|
||||
display: inline-block;
|
||||
width: 50%;
|
||||
margin-bottom: 0px;
|
||||
|
@ -431,12 +295,12 @@ ul.nav.nav-projects-tabs {
|
|||
width: 50%;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
padding-top: 7px;
|
||||
padding-top: 11px;
|
||||
text-align: right;
|
||||
|
||||
.btn-green {
|
||||
margin-top: -2px;
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,11 +346,11 @@ table.table.protected-branches-list tr.no-border {
|
|||
padding-top: 10px;
|
||||
padding-bottom: 4px;
|
||||
|
||||
ul.nav-pills {
|
||||
ul.nav {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.nav-pills li {
|
||||
.nav li {
|
||||
display:inline;
|
||||
}
|
||||
|
||||
|
@ -523,8 +387,7 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.projects-search-form {
|
||||
margin: -$gl-padding;
|
||||
padding: $gl-padding;
|
||||
padding: $gl-padding 0;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0px;
|
||||
|
||||
|
@ -574,10 +437,8 @@ pre.light-well {
|
|||
@include basic-list;
|
||||
|
||||
.project-row {
|
||||
padding: $gl-padding;
|
||||
padding: $gl-padding 0;
|
||||
border-color: $table-border-color;
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
|
||||
&.no-description {
|
||||
.project {
|
||||
|
@ -631,8 +492,6 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.project-last-commit {
|
||||
margin: 0 7px;
|
||||
|
||||
.ci-status {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
@ -662,9 +521,7 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.project-show-readme .readme-holder {
|
||||
margin-left: -$gl-padding;
|
||||
margin-right: -$gl-padding;
|
||||
padding: ($gl-padding + 7px);
|
||||
padding: $gl-padding 0;
|
||||
border-top: 0;
|
||||
|
||||
.edit-project-readme {
|
||||
|
@ -672,3 +529,32 @@ pre.light-well {
|
|||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.git-clone-holder {
|
||||
width: 498px;
|
||||
|
||||
.btn-clipboard {
|
||||
border: 1px solid $border-color;
|
||||
padding: 6px $gl-padding;
|
||||
}
|
||||
|
||||
.project-home-dropdown + & {
|
||||
margin-right: 45px;
|
||||
}
|
||||
|
||||
.clone-options {
|
||||
display: table-cell;
|
||||
a.btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-control {
|
||||
@extend .monospace;
|
||||
background: #FFF;
|
||||
font-size: 14px;
|
||||
margin-left: -1px;
|
||||
cursor: auto;
|
||||
width: 101%;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
.tree-holder {
|
||||
> .nav-block {
|
||||
margin: 11px 0;
|
||||
}
|
||||
|
||||
.file-finder {
|
||||
width: 50%;
|
||||
|
@ -13,7 +16,7 @@
|
|||
|
||||
tr {
|
||||
> td, > th {
|
||||
line-height: 28px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
|
@ -86,12 +89,14 @@
|
|||
|
||||
.blob-commit-info {
|
||||
list-style: none;
|
||||
padding: $gl-padding;
|
||||
background: $background-color;
|
||||
border: 1px solid $border-color;
|
||||
border-bottom: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.commit {
|
||||
padding: $gl-padding 0;
|
||||
padding: 0;
|
||||
|
||||
.commit-row-title {
|
||||
.commit-row-message {
|
||||
|
@ -115,3 +120,8 @@
|
|||
font-weight: normal;
|
||||
color: $md-link-color;
|
||||
}
|
||||
|
||||
.tree-controls {
|
||||
float: right;
|
||||
margin-top: 11px;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ class AbuseReportsController < ApplicationController
|
|||
def new
|
||||
@abuse_report = AbuseReport.new
|
||||
@abuse_report.user_id = params[:user_id]
|
||||
@ref_url = params.fetch(:ref_url, '')
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -73,6 +73,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:metrics_pool_size,
|
||||
:metrics_timeout,
|
||||
:metrics_method_call_threshold,
|
||||
:metrics_sample_interval,
|
||||
:recaptcha_enabled,
|
||||
:recaptcha_site_key,
|
||||
:recaptcha_private_key,
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
class Admin::BroadcastMessagesController < Admin::ApplicationController
|
||||
before_action :broadcast_messages
|
||||
before_action :finder, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@broadcast_message = BroadcastMessage.new
|
||||
@broadcast_messages = BroadcastMessage.reorder("starts_at ASC").page(params[:page])
|
||||
@broadcast_message = BroadcastMessage.new
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def create
|
||||
|
@ -15,8 +19,16 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @broadcast_message.update(broadcast_message_params)
|
||||
redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully updated.'
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
BroadcastMessage.find(params[:id]).destroy
|
||||
@broadcast_message.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_back_or_default(default: { action: 'index' }) }
|
||||
|
@ -26,14 +38,17 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def broadcast_messages
|
||||
@broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page])
|
||||
def finder
|
||||
@broadcast_message = BroadcastMessage.find(params[:id])
|
||||
end
|
||||
|
||||
def broadcast_message_params
|
||||
params.require(:broadcast_message).permit(
|
||||
:alert_type, :color, :ends_at, :font,
|
||||
:message, :starts_at
|
||||
)
|
||||
params.require(:broadcast_message).permit(%i(
|
||||
color
|
||||
ends_at
|
||||
font
|
||||
message
|
||||
starts_at
|
||||
))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,6 +26,7 @@ class Admin::IdentitiesController < Admin::ApplicationController
|
|||
|
||||
def update
|
||||
if @identity.update_attributes(identity_params)
|
||||
RepairLdapBlockedUserService.new(@user).execute
|
||||
redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully updated.'
|
||||
else
|
||||
render :edit
|
||||
|
@ -34,6 +35,7 @@ class Admin::IdentitiesController < Admin::ApplicationController
|
|||
|
||||
def destroy
|
||||
if @identity.destroy
|
||||
RepairLdapBlockedUserService.new(@user).execute
|
||||
redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully removed.'
|
||||
else
|
||||
redirect_to admin_user_identities_path(@user), alert: 'Failed to remove user identity.'
|
||||
|
|
|
@ -40,7 +40,9 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
end
|
||||
|
||||
def unblock
|
||||
if user.activate
|
||||
if user.ldap_blocked?
|
||||
redirect_back_or_admin_user(alert: "This user cannot be unlocked manually from GitLab")
|
||||
elsif user.activate
|
||||
redirect_back_or_admin_user(notice: "Successfully unblocked")
|
||||
else
|
||||
redirect_back_or_admin_user(alert: "Error occurred. User was not unblocked")
|
||||
|
|
|
@ -115,7 +115,7 @@ class ApplicationController < ActionController::Base
|
|||
# localhost/group/project
|
||||
#
|
||||
if id =~ /\.git\Z/
|
||||
redirect_to request.original_url.gsub(/\.git\Z/, '') and return
|
||||
redirect_to request.original_url.gsub(/\.git\/?\Z/, '') and return
|
||||
end
|
||||
|
||||
project_path = "#{namespace}/#{id}"
|
||||
|
|
56
app/controllers/projects/artifacts_controller.rb
Normal file
56
app/controllers/projects/artifacts_controller.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
class Projects::ArtifactsController < Projects::ApplicationController
|
||||
layout 'project'
|
||||
before_action :authorize_read_build_artifacts!
|
||||
|
||||
def download
|
||||
unless artifacts_file.file_storage?
|
||||
return redirect_to artifacts_file.url
|
||||
end
|
||||
|
||||
unless artifacts_file.exists?
|
||||
return render_404
|
||||
end
|
||||
|
||||
send_file artifacts_file.path, disposition: 'attachment'
|
||||
end
|
||||
|
||||
def browse
|
||||
return render_404 unless build.artifacts?
|
||||
|
||||
directory = params[:path] ? "#{params[:path]}/" : ''
|
||||
@entry = build.artifacts_metadata_entry(directory)
|
||||
|
||||
return render_404 unless @entry.exists?
|
||||
end
|
||||
|
||||
def file
|
||||
entry = build.artifacts_metadata_entry(params[:path])
|
||||
|
||||
if entry.exists?
|
||||
render json: { archive: build.artifacts_file.path,
|
||||
entry: Base64.encode64(entry.path) }
|
||||
else
|
||||
render json: {}, status: 404
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build
|
||||
@build ||= project.builds.unscoped.find_by!(id: params[:build_id])
|
||||
end
|
||||
|
||||
def artifacts_file
|
||||
@artifacts_file ||= build.artifacts_file
|
||||
end
|
||||
|
||||
def authorize_read_build_artifacts!
|
||||
unless can?(current_user, :read_build_artifacts, @project)
|
||||
if current_user.nil?
|
||||
return authenticate_user!
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,7 +2,6 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
before_action :build, except: [:index, :cancel_all]
|
||||
|
||||
before_action :authorize_manage_builds!, except: [:index, :show, :status]
|
||||
before_action :authorize_download_build_artifacts!, only: [:download]
|
||||
|
||||
layout "project"
|
||||
|
||||
|
@ -43,7 +42,7 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
|
||||
def retry
|
||||
unless @build.retryable?
|
||||
return page_404
|
||||
return render_404
|
||||
end
|
||||
|
||||
build = Ci::Build.retry(@build)
|
||||
|
@ -51,18 +50,6 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
redirect_to build_path(build)
|
||||
end
|
||||
|
||||
def download
|
||||
unless artifacts_file.file_storage?
|
||||
return redirect_to artifacts_file.url
|
||||
end
|
||||
|
||||
unless artifacts_file.exists?
|
||||
return not_found!
|
||||
end
|
||||
|
||||
send_file artifacts_file.path, disposition: 'attachment'
|
||||
end
|
||||
|
||||
def status
|
||||
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
|
||||
end
|
||||
|
@ -79,27 +66,13 @@ class Projects::BuildsController < Projects::ApplicationController
|
|||
@build ||= project.builds.unscoped.find_by!(id: params[:id])
|
||||
end
|
||||
|
||||
def artifacts_file
|
||||
build.artifacts_file
|
||||
end
|
||||
|
||||
def build_path(build)
|
||||
namespace_project_build_path(build.project.namespace, build.project, build)
|
||||
end
|
||||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return page_404
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_download_build_artifacts!
|
||||
unless can?(current_user, :download_build_artifacts, @project)
|
||||
if current_user.nil?
|
||||
return authenticate_user!
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -79,7 +79,7 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
|
||||
def authorize_manage_builds!
|
||||
unless can?(current_user, :manage_builds, project)
|
||||
return page_404
|
||||
return render_404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,7 +49,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
assignee_id: ""
|
||||
)
|
||||
|
||||
@issue = @project.issues.new(issue_params)
|
||||
@issue = @noteable = @project.issues.new(issue_params)
|
||||
respond_with(@issue)
|
||||
end
|
||||
|
||||
|
@ -61,7 +61,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
@note = @project.notes.new(noteable: @issue)
|
||||
@notes = @issue.notes.nonawards.with_associations.fresh
|
||||
@noteable = @issue
|
||||
@merge_requests = @issue.referenced_merge_requests
|
||||
@merge_requests = @issue.referenced_merge_requests(current_user)
|
||||
|
||||
respond_with(@issue)
|
||||
end
|
||||
|
|
|
@ -90,6 +90,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
def new
|
||||
params[:merge_request] ||= ActionController::Parameters.new(source_project: @project)
|
||||
@merge_request = MergeRequests::BuildService.new(project, current_user, merge_request_params).execute
|
||||
@noteable = @merge_request
|
||||
|
||||
@target_branches = if @merge_request.target_project
|
||||
@merge_request.target_project.repository.branch_names
|
||||
|
|
|
@ -25,7 +25,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@snippet = @project.snippets.build
|
||||
@snippet = @noteable = @project.snippets.build
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
25
app/controllers/sent_notifications_controller.rb
Normal file
25
app/controllers/sent_notifications_controller.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
class SentNotificationsController < ApplicationController
|
||||
skip_before_action :authenticate_user!
|
||||
|
||||
def unsubscribe
|
||||
@sent_notification = SentNotification.for(params[:id])
|
||||
return render_404 unless @sent_notification && @sent_notification.unsubscribable?
|
||||
|
||||
noteable = @sent_notification.noteable
|
||||
noteable.unsubscribe(@sent_notification.recipient)
|
||||
|
||||
flash[:notice] = "You have been unsubscribed from this thread."
|
||||
if current_user
|
||||
case noteable
|
||||
when Issue
|
||||
redirect_to issue_path(noteable)
|
||||
when MergeRequest
|
||||
redirect_to merge_request_path(noteable)
|
||||
else
|
||||
redirect_to root_path
|
||||
end
|
||||
else
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
end
|
|
@ -181,10 +181,6 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def broadcast_message
|
||||
BroadcastMessage.current
|
||||
end
|
||||
|
||||
# Render a `time` element with Javascript-based relative date and tooltip
|
||||
#
|
||||
# time - Time object
|
||||
|
@ -266,7 +262,7 @@ module ApplicationHelper
|
|||
state: params[:state],
|
||||
scope: params[:scope],
|
||||
label_name: params[:label_name],
|
||||
milestone_id: params[:milestone_id],
|
||||
milestone_title: params[:milestone_title],
|
||||
assignee_id: params[:assignee_id],
|
||||
author_id: params[:author_id],
|
||||
sort: params[:sort],
|
||||
|
|
|
@ -1,16 +1,34 @@
|
|||
module BroadcastMessagesHelper
|
||||
def broadcast_styling(broadcast_message)
|
||||
styling = ''
|
||||
def broadcast_message(message = BroadcastMessage.current)
|
||||
return unless message.present?
|
||||
|
||||
content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do
|
||||
icon('bullhorn') << ' ' << message.message
|
||||
end
|
||||
end
|
||||
|
||||
def broadcast_message_style(broadcast_message)
|
||||
style = ''
|
||||
|
||||
if broadcast_message.color.present?
|
||||
styling << "background-color: #{broadcast_message.color}"
|
||||
styling << '; ' if broadcast_message.font.present?
|
||||
style << "background-color: #{broadcast_message.color}"
|
||||
style << '; ' if broadcast_message.font.present?
|
||||
end
|
||||
|
||||
if broadcast_message.font.present?
|
||||
styling << "color: #{broadcast_message.font}"
|
||||
style << "color: #{broadcast_message.font}"
|
||||
end
|
||||
|
||||
styling
|
||||
style
|
||||
end
|
||||
|
||||
def broadcast_message_status(broadcast_message)
|
||||
if broadcast_message.active?
|
||||
'Active'
|
||||
elsif broadcast_message.ended?
|
||||
'Expired'
|
||||
else
|
||||
'Pending'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,7 +17,7 @@ module ButtonHelper
|
|||
def clipboard_button(data = {})
|
||||
content_tag :button,
|
||||
icon('clipboard'),
|
||||
class: 'btn btn-xs btn-clipboard',
|
||||
class: 'btn btn-clipboard',
|
||||
data: data,
|
||||
type: :button
|
||||
end
|
||||
|
|
|
@ -27,13 +27,15 @@ module EventsHelper
|
|||
key = key.to_s
|
||||
active = 'active' if @event_filter.active?(key)
|
||||
link_opts = {
|
||||
class: "event-filter-link btn btn-default #{active}",
|
||||
class: "event-filter-link",
|
||||
id: "#{key}_event_filter",
|
||||
title: "Filter by #{tooltip.downcase}",
|
||||
}
|
||||
|
||||
link_to request.path, link_opts do
|
||||
content_tag(:span, ' ' + tooltip)
|
||||
content_tag :li, class: active do
|
||||
link_to request.path, link_opts do
|
||||
content_tag(:span, ' ' + tooltip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ module GitlabMarkdownHelper
|
|||
def render_wiki_content(wiki_page)
|
||||
case wiki_page.format
|
||||
when :markdown
|
||||
markdown(wiki_page.content)
|
||||
markdown(wiki_page.content, pipeline: :wiki, project_wiki: @project_wiki)
|
||||
when :asciidoc
|
||||
asciidoc(wiki_page.content)
|
||||
else
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
module Emails
|
||||
module Issues
|
||||
def new_issue_email(recipient_id, issue_id)
|
||||
issue_mail_with_notification(issue_id, recipient_id) do
|
||||
mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id))
|
||||
end
|
||||
setup_issue_mail(issue_id, recipient_id)
|
||||
|
||||
mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id))
|
||||
end
|
||||
|
||||
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id)
|
||||
issue_mail_with_notification(issue_id, recipient_id) do
|
||||
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
setup_issue_mail(issue_id, recipient_id)
|
||||
|
||||
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
|
||||
def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
|
||||
issue_mail_with_notification(issue_id, recipient_id) do
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
setup_issue_mail(issue_id, recipient_id)
|
||||
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
|
||||
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
|
||||
issue_mail_with_notification(issue_id, recipient_id) do
|
||||
@issue_status = status
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
setup_issue_mail(issue_id, recipient_id)
|
||||
|
||||
@issue_status = status
|
||||
@updated_by = User.find updated_by_user_id
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -38,14 +38,12 @@ module Emails
|
|||
}
|
||||
end
|
||||
|
||||
def issue_mail_with_notification(issue_id, recipient_id)
|
||||
def setup_issue_mail(issue_id, recipient_id)
|
||||
@issue = Issue.find(issue_id)
|
||||
@project = @issue.project
|
||||
@target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
|
||||
|
||||
yield
|
||||
|
||||
SentNotification.record(@issue, recipient_id, reply_key)
|
||||
@sent_notification = SentNotification.record(@issue, recipient_id, reply_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,77 +1,64 @@
|
|||
module Emails
|
||||
module MergeRequests
|
||||
def new_merge_request_email(recipient_id, merge_request_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
@project = @merge_request.project
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
|
||||
mail_new_thread(@merge_request,
|
||||
from: sender(@merge_request.author_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||
|
||||
SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
end
|
||||
|
||||
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
|
||||
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
|
||||
@project = @merge_request.project
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
mail_answer_thread(@merge_request,
|
||||
from: sender(updated_by_user_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||
|
||||
SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
end
|
||||
|
||||
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
|
||||
@updated_by = User.find updated_by_user_id
|
||||
@project = @merge_request.project
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
mail_answer_thread(@merge_request,
|
||||
from: sender(updated_by_user_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||
|
||||
SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
end
|
||||
|
||||
def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
@project = @merge_request.project
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
|
||||
mail_answer_thread(@merge_request,
|
||||
from: sender(updated_by_user_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||
|
||||
SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
end
|
||||
|
||||
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
|
||||
@mr_status = status
|
||||
@project = @merge_request.project
|
||||
@updated_by = User.find updated_by_user_id
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
mail_answer_thread(@merge_request,
|
||||
from: sender(updated_by_user_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
|
||||
end
|
||||
|
||||
SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
private
|
||||
|
||||
def setup_merge_request_mail(merge_request_id, recipient_id)
|
||||
@merge_request = MergeRequest.find(merge_request_id)
|
||||
@project = @merge_request.project
|
||||
@target_url = namespace_project_merge_request_url(@project.namespace,
|
||||
@project,
|
||||
@merge_request)
|
||||
|
||||
@sent_notification = SentNotification.record(@merge_request, recipient_id, reply_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
module Emails
|
||||
module Notes
|
||||
def note_commit_email(recipient_id, note_id)
|
||||
note_mail_with_notification(note_id, recipient_id) do
|
||||
@commit = @note.noteable
|
||||
@target_url = namespace_project_commit_url(*note_target_url_options)
|
||||
setup_note_mail(note_id, recipient_id)
|
||||
|
||||
mail_answer_thread(@commit,
|
||||
from: sender(@note.author_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@commit.title} (#{@commit.short_id})"))
|
||||
end
|
||||
@commit = @note.noteable
|
||||
@target_url = namespace_project_commit_url(*note_target_url_options)
|
||||
|
||||
mail_answer_thread(@commit,
|
||||
from: sender(@note.author_id),
|
||||
to: recipient(recipient_id),
|
||||
subject: subject("#{@commit.title} (#{@commit.short_id})"))
|
||||
end
|
||||
|
||||
def note_issue_email(recipient_id, note_id)
|
||||
note_mail_with_notification(note_id, recipient_id) do
|
||||
@issue = @note.noteable
|
||||
@target_url = namespace_project_issue_url(*note_target_url_options)
|
||||
mail_answer_thread(@issue, note_thread_options(recipient_id))
|
||||
end
|
||||
setup_note_mail(note_id, recipient_id)
|
||||
|
||||
@issue = @note.noteable
|
||||
@target_url = namespace_project_issue_url(*note_target_url_options)
|
||||
mail_answer_thread(@issue, note_thread_options(recipient_id))
|
||||
end
|
||||
|
||||
def note_merge_request_email(recipient_id, note_id)
|
||||
note_mail_with_notification(note_id, recipient_id) do
|
||||
@merge_request = @note.noteable
|
||||
@target_url = namespace_project_merge_request_url(*note_target_url_options)
|
||||
mail_answer_thread(@merge_request, note_thread_options(recipient_id))
|
||||
end
|
||||
setup_note_mail(note_id, recipient_id)
|
||||
|
||||
@merge_request = @note.noteable
|
||||
@target_url = namespace_project_merge_request_url(*note_target_url_options)
|
||||
mail_answer_thread(@merge_request, note_thread_options(recipient_id))
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -42,13 +42,11 @@ module Emails
|
|||
}
|
||||
end
|
||||
|
||||
def note_mail_with_notification(note_id, recipient_id)
|
||||
def setup_note_mail(note_id, recipient_id)
|
||||
@note = Note.find(note_id)
|
||||
@project = @note.project
|
||||
|
||||
yield
|
||||
|
||||
SentNotification.record_note(@note, recipient_id, reply_key)
|
||||
@sent_notification = SentNotification.record_note(@note, recipient_id, reply_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -107,10 +107,9 @@ class Notify < BaseMailer
|
|||
end
|
||||
|
||||
headers["X-GitLab-#{model.class.name}-ID"] = model.id
|
||||
headers['X-GitLab-Reply-Key'] = reply_key
|
||||
|
||||
if reply_key
|
||||
headers['X-GitLab-Reply-Key'] = reply_key
|
||||
|
||||
if Gitlab::IncomingEmail.enabled?
|
||||
address = Mail::Address.new(Gitlab::IncomingEmail.reply_address(reply_key))
|
||||
address.display_name = @project.name_with_namespace
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ class Ability
|
|||
@project_report_rules ||= project_guest_rules + [
|
||||
:create_commit_status,
|
||||
:read_commit_statuses,
|
||||
:read_build_artifacts,
|
||||
:download_code,
|
||||
:fork_project,
|
||||
:create_project_snippet,
|
||||
|
@ -175,7 +176,6 @@ class Ability
|
|||
:create_merge_request,
|
||||
:create_wiki,
|
||||
:manage_builds,
|
||||
:download_build_artifacts,
|
||||
:push_code
|
||||
]
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
# message :text not null
|
||||
# starts_at :datetime
|
||||
# ends_at :datetime
|
||||
# alert_type :integer
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# color :string(255)
|
||||
|
@ -23,7 +22,22 @@ class BroadcastMessage < ActiveRecord::Base
|
|||
validates :color, allow_blank: true, color: true
|
||||
validates :font, allow_blank: true, color: true
|
||||
|
||||
default_value_for :color, '#E75E40'
|
||||
default_value_for :font, '#FFFFFF'
|
||||
|
||||
def self.current
|
||||
where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last
|
||||
where("ends_at > :now AND starts_at <= :now", now: Time.zone.now).last
|
||||
end
|
||||
|
||||
def active?
|
||||
started? && !ended?
|
||||
end
|
||||
|
||||
def started?
|
||||
Time.zone.now >= starts_at
|
||||
end
|
||||
|
||||
def ended?
|
||||
ends_at < Time.zone.now
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,10 +30,12 @@
|
|||
# description :string(255)
|
||||
# artifacts_file :text
|
||||
# gl_project_id :integer
|
||||
# artifacts_metadata :text
|
||||
#
|
||||
|
||||
module Ci
|
||||
class Build < CommitStatus
|
||||
include Gitlab::Application.routes.url_helpers
|
||||
LAZY_ATTRIBUTES = ['trace']
|
||||
|
||||
belongs_to :runner, class_name: 'Ci::Runner'
|
||||
|
@ -49,6 +51,7 @@ module Ci
|
|||
scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
|
||||
|
||||
mount_uploader :artifacts_file, ArtifactUploader
|
||||
mount_uploader :artifacts_metadata, ArtifactUploader
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
|
@ -125,6 +128,14 @@ module Ci
|
|||
!self.commit.latest_builds_for_ref(self.ref).include?(self)
|
||||
end
|
||||
|
||||
def depends_on_builds
|
||||
# Get builds of the same type
|
||||
latest_builds = self.commit.builds.similar(self).latest
|
||||
|
||||
# Return builds from previous stages
|
||||
latest_builds.where('stage_idx < ?', stage_idx)
|
||||
end
|
||||
|
||||
def trace_html
|
||||
html = Ci::Ansi2html::convert(trace) if trace.present?
|
||||
html || ''
|
||||
|
@ -291,21 +302,18 @@ module Ci
|
|||
end
|
||||
|
||||
def target_url
|
||||
Gitlab::Application.routes.url_helpers.
|
||||
namespace_project_build_url(project.namespace, project, self)
|
||||
namespace_project_build_url(project.namespace, project, self)
|
||||
end
|
||||
|
||||
def cancel_url
|
||||
if active?
|
||||
Gitlab::Application.routes.url_helpers.
|
||||
cancel_namespace_project_build_path(project.namespace, project, self)
|
||||
cancel_namespace_project_build_path(project.namespace, project, self)
|
||||
end
|
||||
end
|
||||
|
||||
def retry_url
|
||||
if retryable?
|
||||
Gitlab::Application.routes.url_helpers.
|
||||
retry_namespace_project_build_path(project.namespace, project, self)
|
||||
retry_namespace_project_build_path(project.namespace, project, self)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -321,20 +329,35 @@ module Ci
|
|||
pending? && !any_runners_online?
|
||||
end
|
||||
|
||||
def download_url
|
||||
if artifacts_file.exists?
|
||||
Gitlab::Application.routes.url_helpers.
|
||||
download_namespace_project_build_path(project.namespace, project, self)
|
||||
end
|
||||
end
|
||||
|
||||
def execute_hooks
|
||||
build_data = Gitlab::BuildDataBuilder.build(self)
|
||||
project.execute_hooks(build_data.dup, :build_hooks)
|
||||
project.execute_services(build_data.dup, :build_hooks)
|
||||
end
|
||||
|
||||
def artifacts?
|
||||
artifacts_file.exists?
|
||||
end
|
||||
|
||||
def artifacts_download_url
|
||||
if artifacts?
|
||||
download_namespace_project_build_artifacts_path(project.namespace, project, self)
|
||||
end
|
||||
end
|
||||
|
||||
def artifacts_browse_url
|
||||
if artifacts_browser_supported?
|
||||
browse_namespace_project_build_artifacts_path(project.namespace, project, self)
|
||||
end
|
||||
end
|
||||
|
||||
def artifacts_browser_supported?
|
||||
artifacts? && artifacts_metadata.exists?
|
||||
end
|
||||
|
||||
def artifacts_metadata_entry(path)
|
||||
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path).to_entry
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ module Ci
|
|||
trigger_requests.last
|
||||
end
|
||||
|
||||
def last_used
|
||||
last_trigger_request.try(:created_at)
|
||||
end
|
||||
|
||||
def short_token
|
||||
token[0...10]
|
||||
end
|
||||
|
|
|
@ -18,8 +18,12 @@ module Ci
|
|||
|
||||
belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
|
||||
|
||||
validates_presence_of :key
|
||||
validates_uniqueness_of :key, scope: :gl_project_id
|
||||
validates :key,
|
||||
presence: true,
|
||||
length: { within: 0..255 },
|
||||
format: { with: /\A[a-zA-Z0-9_]+\z/,
|
||||
message: "can contain only letters, digits and '_'." }
|
||||
|
||||
attr_encrypted :value, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
|
||||
end
|
||||
|
|
|
@ -56,6 +56,8 @@ class CommitStatus < ActiveRecord::Base
|
|||
scope :ordered, -> { order(:ref, :stage_idx, :name) }
|
||||
scope :for_ref, ->(ref) { where(ref: ref) }
|
||||
|
||||
AVAILABLE_STATUSES = ['pending', 'running', 'success', 'failed', 'canceled']
|
||||
|
||||
state_machine :status, initial: :pending do
|
||||
event :run do
|
||||
transition pending: :running
|
||||
|
@ -131,7 +133,11 @@ class CommitStatus < ActiveRecord::Base
|
|||
false
|
||||
end
|
||||
|
||||
def download_url
|
||||
def artifacts_download_url
|
||||
nil
|
||||
end
|
||||
|
||||
def artifacts_browse_url
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -119,6 +119,12 @@ module Issuable
|
|||
update(subscribed: !subscribed?(user))
|
||||
end
|
||||
|
||||
def unsubscribe(user)
|
||||
subscriptions.
|
||||
find_or_initialize_by(user_id: user.id).
|
||||
update(subscribed: false)
|
||||
end
|
||||
|
||||
def to_hook_data(user)
|
||||
{
|
||||
object_kind: self.class.name.underscore,
|
||||
|
|
|
@ -48,8 +48,8 @@ class WebHook < ActiveRecord::Base
|
|||
else
|
||||
post_url = url.gsub("#{parsed_url.userinfo}@", "")
|
||||
auth = {
|
||||
username: URI.decode(parsed_url.user),
|
||||
password: URI.decode(parsed_url.password),
|
||||
username: CGI.unescape(parsed_url.user),
|
||||
password: CGI.unescape(parsed_url.password),
|
||||
}
|
||||
response = WebHook.post(post_url,
|
||||
body: data.to_json,
|
||||
|
|
|
@ -18,4 +18,8 @@ class Identity < ActiveRecord::Base
|
|||
validates :provider, presence: true
|
||||
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
|
||||
validates :user_id, uniqueness: { scope: :provider }
|
||||
|
||||
def ldap?
|
||||
provider.starts_with?('ldap')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -85,10 +85,10 @@ class Issue < ActiveRecord::Base
|
|||
reference
|
||||
end
|
||||
|
||||
def referenced_merge_requests
|
||||
def referenced_merge_requests(current_user = nil)
|
||||
Gitlab::ReferenceExtractor.lazily do
|
||||
[self, *notes].flat_map do |note|
|
||||
note.all_references.merge_requests
|
||||
note.all_references(current_user).merge_requests
|
||||
end
|
||||
end.sort_by(&:iid)
|
||||
end
|
||||
|
|
|
@ -358,6 +358,10 @@ class Note < ActiveRecord::Base
|
|||
!system? && !is_award
|
||||
end
|
||||
|
||||
def cross_reference_not_visible_for?(user)
|
||||
cross_reference? && referenced_mentionables(user).empty?
|
||||
end
|
||||
|
||||
# Checks if note is an award added as a comment
|
||||
#
|
||||
# If note is an award, this method sets is_award to true
|
||||
|
|
|
@ -397,7 +397,7 @@ class Project < ActiveRecord::Base
|
|||
result.password = '*****' unless result.password.nil?
|
||||
result.to_s
|
||||
rescue
|
||||
original_url
|
||||
self.import_url
|
||||
end
|
||||
|
||||
def check_limit
|
||||
|
|
|
@ -120,13 +120,13 @@ class HipchatService < Service
|
|||
message << "#{push[:user_name]} "
|
||||
if Gitlab::Git.blank_ref?(before)
|
||||
message << "pushed new #{ref_type} <a href=\""\
|
||||
"#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"\
|
||||
"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"\
|
||||
" to #{project_link}\n"
|
||||
elsif Gitlab::Git.blank_ref?(after)
|
||||
message << "removed #{ref_type} <b>#{ref}</b> from <a href=\"#{project.web_url}\">#{project_name}</a> \n"
|
||||
else
|
||||
message << "pushed to #{ref_type} <a href=\""\
|
||||
"#{project.web_url}/commits/#{URI.escape(ref)}\">#{ref}</a> "
|
||||
"#{project.web_url}/commits/#{CGI.escape(ref)}\">#{ref}</a> "
|
||||
message << "of <a href=\"#{project.web_url}\">#{project.name_with_namespace.gsub!(/\s/,'')}</a> "
|
||||
message << "(<a href=\"#{project.web_url}/compare/#{before}...#{after}\">Compare changes</a>)"
|
||||
|
||||
|
@ -255,8 +255,8 @@ class HipchatService < Service
|
|||
status = data[:commit][:status]
|
||||
duration = data[:commit][:duration]
|
||||
|
||||
branch_link = "<a href=\"#{project_url}/commits/#{URI.escape(ref)}\">#{ref}</a>"
|
||||
commit_link = "<a href=\"#{project_url}/commit/#{URI.escape(sha)}/builds\">#{Commit.truncate_sha(sha)}</a>"
|
||||
branch_link = "<a href=\"#{project_url}/commits/#{CGI.escape(ref)}\">#{ref}</a>"
|
||||
commit_link = "<a href=\"#{project_url}/commit/#{CGI.escape(sha)}/builds\">#{Commit.truncate_sha(sha)}</a>"
|
||||
|
||||
"#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status(status)} in #{duration} second(s)"
|
||||
end
|
||||
|
|
|
@ -38,6 +38,10 @@ class ProjectWiki
|
|||
[Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
|
||||
end
|
||||
|
||||
def wiki_base_path
|
||||
["/", @project.path_with_namespace, "/wikis"].join('')
|
||||
end
|
||||
|
||||
# Returns the Gollum::Wiki object.
|
||||
def wiki
|
||||
@wiki ||= begin
|
||||
|
|
|
@ -25,8 +25,6 @@ class SentNotification < ActiveRecord::Base
|
|||
|
||||
class << self
|
||||
def reply_key
|
||||
return nil unless Gitlab::IncomingEmail.enabled?
|
||||
|
||||
SecureRandom.hex(16)
|
||||
end
|
||||
|
||||
|
@ -59,11 +57,15 @@ class SentNotification < ActiveRecord::Base
|
|||
|
||||
def record_note(note, recipient_id, reply_key, params = {})
|
||||
params[:line_code] = note.line_code
|
||||
|
||||
|
||||
record(note.noteable, recipient_id, reply_key, params)
|
||||
end
|
||||
end
|
||||
|
||||
def unsubscribable?
|
||||
!for_commit?
|
||||
end
|
||||
|
||||
def for_commit?
|
||||
noteable_type == "Commit"
|
||||
end
|
||||
|
@ -75,4 +77,8 @@ class SentNotification < ActiveRecord::Base
|
|||
super
|
||||
end
|
||||
end
|
||||
|
||||
def to_param
|
||||
self.reply_key
|
||||
end
|
||||
end
|
||||
|
|
|
@ -196,10 +196,22 @@ class User < ActiveRecord::Base
|
|||
state_machine :state, initial: :active do
|
||||
event :block do
|
||||
transition active: :blocked
|
||||
transition ldap_blocked: :blocked
|
||||
end
|
||||
|
||||
event :ldap_block do
|
||||
transition active: :ldap_blocked
|
||||
end
|
||||
|
||||
event :activate do
|
||||
transition blocked: :active
|
||||
transition ldap_blocked: :active
|
||||
end
|
||||
|
||||
state :blocked, :ldap_blocked do
|
||||
def blocked?
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -207,7 +219,7 @@ class User < ActiveRecord::Base
|
|||
|
||||
# Scopes
|
||||
scope :admins, -> { where(admin: true) }
|
||||
scope :blocked, -> { with_state(:blocked) }
|
||||
scope :blocked, -> { with_states(:blocked, :ldap_blocked) }
|
||||
scope :active, -> { with_state(:active) }
|
||||
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
|
||||
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members)') }
|
||||
|
|
|
@ -169,7 +169,7 @@ class WikiPage
|
|||
private
|
||||
|
||||
def set_attributes
|
||||
attributes[:slug] = @page.escaped_url_path
|
||||
attributes[:slug] = @page.url_path
|
||||
attributes[:title] = @page.title
|
||||
attributes[:format] = @page.format
|
||||
end
|
||||
|
|
|
@ -44,7 +44,7 @@ module MergeRequests
|
|||
def after_merge
|
||||
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
|
||||
|
||||
if params[:should_remove_source_branch]
|
||||
if params[:should_remove_source_branch].present?
|
||||
DeleteBranchService.new(@merge_request.source_project, current_user).
|
||||
execute(merge_request.source_branch)
|
||||
end
|
||||
|
|
17
app/services/repair_ldap_blocked_user_service.rb
Normal file
17
app/services/repair_ldap_blocked_user_service.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
class RepairLdapBlockedUserService
|
||||
attr_accessor :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
def execute
|
||||
user.block if ldap_hard_blocked?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ldap_hard_blocked?
|
||||
user.ldap_blocked? && !user.ldap_user?
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue