Commit 6b028ed8 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream' into 'master'

CE upstream

@dzaporozhets Please resolve these conflicts
```
Unmerged paths:
  (use "git add <file>..." to mark resolution)

	both modified:   app/views/groups/group_members/index.html.haml
	both modified:   app/views/projects/project_members/index.html.haml
```

See merge request !67
parents f4422dba 8588b70f
......@@ -888,7 +888,7 @@ Lint/RequireParentheses:
Lint/RescueException:
Description: 'Avoid rescuing the Exception class.'
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-blind-rescues'
Enabled: false
Enabled: true
Lint/ShadowingOuterLocalVariable:
Description: >-
......
......@@ -2,6 +2,17 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased)
- Fix: Assignee selector is empty when 'Unassigned' is selected (Jose Corcuera)
- Fix 500 error when update group member permission
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
- Add ignore whitespace change option to commit view
- Fire update hook from GitLab
v 8.2.2
- Fix 404 in redirection after removing a project (Stan Hu)
- Ensure cached application settings are refreshed at startup (Stan Hu)
- Fix Error 500 when viewing user's personal projects from admin page (Stan Hu)
- Fix: Raw private snippets access workflow
- Prevent "413 Request entity too large" errors when pushing large files with LFS
v 8.2.1
- Forcefully update builds that didn't want to update with state machine
......@@ -22,7 +33,6 @@ v 8.2.0
- Expose build artifacts path as config option
- Fix grouping of contributors by email in graph.
- Improved performance of finding issues with/without labels
- Remove CSS property preventing hard tabs from rendering in Chromium 45 (Stan Hu)
- Fix Drone CI service template not saving properly (Stan Hu)
- Fix avatars not showing in Atom feeds and project issues when Gravatar disabled (Stan Hu)
- Added a GitLab specific profiling tool called "Sherlock" (see GitLab CE merge request #1749)
......
......@@ -27,6 +27,16 @@ The channels people will reach out on can be found on the [getting help page](ht
Sign up for the mailinglist, answer GitLab questions on StackOverflow or respond in the IRC channel.
You can also sign up on [CodeTriage](http://www.codetriage.com/gitlabhq/gitlabhq) to help with one issue every day.
## I want to contribute!
If you want to contribute to GitLab, but are not sure where to start,
look for [issues](https://gitlab.com/gitlab-org/gitlab-ce/issues?milestone_id=&scope=all&sort=created_desc&state=opened&utf8=%E2%9C%93&assignee_id=&author_id=&milestone_title=&label_name=up-for-grabs)
with the label `up-for-grabs`.
These issues will be of reasonable size and challenge, for anyone to start
contributing to GitLab.
This was inspired by [an article by Kent C. Dodds](https://medium.com/@kentcdodds/first-timers-only-78281ea47455#.i2f363mx4).
## Issue tracker
To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/getting-help/).
......@@ -47,10 +57,10 @@ Please send a merge request with a tested solution or a merge request with a fai
1. **Observed behavior**
1. **Relevant logs and/or screenshots:** Please use code blocks (\`\`\`) to format console output, logs, and code as it's very hard to read otherwise.
1. **Output of checks**
* Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (`sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing
* Results of GitLab [Application Check](doc/install/installation.md#check-application-status) (For installations with omnibus-gitlab package: `sudo gitlab-rake gitlab:check SANITIZE=true`); For installations from source: `sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production SANITIZE=true`); we will only investigate if the tests are passing
* Version of GitLab you are running; we will only investigate issues in the latest stable and development releases as per the [maintenance policy](MAINTENANCE.md)
* Add the last commit SHA-1 of the GitLab version you used to replicate the issue (obtainable from the help page)
* Describe your setup (use relevant parts from `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
* Describe your setup (use relevant parts from the env info: For installations with omnibus-gitlab package: `sudo gitlab-rake gitlab:env:info`; For installations from source: `sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production`)
1. **Possible fixes**: If you can, link to the line of code that might be responsible for the problem
## Merge requests
......
source "https://rubygems.org"
gem 'rails', '4.1.14'
gem 'rails', '4.2.4'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with
gem 'responders', '~> 2.0'
# Specify a sprockets version due to security issue
# See https://groups.google.com/forum/#!topic/rubyonrails-security/doAVp0YaTqY
......@@ -16,7 +20,7 @@ gem "pg", '~> 0.18.2', group: :postgres
# Authentication libraries
gem 'devise', '~> 3.5.2'
gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.1.3'
gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-facebook', '~> 3.0.0'
......@@ -29,7 +33,7 @@ gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd'
gem 'gssapi', group: :kerberos
gem 'rack-oauth2', '~> 1.0.5'
gem 'rack-oauth2', '~> 1.2.1'
# Two-factor authentication
gem 'devise-two-factor', '~> 2.0.0'
......@@ -97,9 +101,10 @@ gem 'redcarpet', '~> 3.3.3'
gem 'RedCloth', '~> 4.2.9'
gem 'rdoc', '~>3.6'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~>0.3.6'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2'
gem 'net-ssh', '~> 3.0.1'
# Diffs
gem 'diffy', '~> 3.0.3'
......@@ -127,8 +132,7 @@ gem 'sidetiq', '~> 0.6.3'
gem "httparty", '~> 0.13.3'
# Colored output to console
gem "colored", '~> 1.2'
gem "colorize", '~> 0.5.8'
gem "colorize", '~> 0.7.0'
# GitLab settings
gem 'settingslogic', '~> 2.0.9'
......@@ -156,7 +160,7 @@ gem "gemnasium-gitlab-service", "~> 0.2"
gem "slack-notifier", "~> 1.2.0"
# Asana integration
gem 'asana', '~> 0.0.6'
gem 'asana', '~> 0.4.0'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
......@@ -189,13 +193,13 @@ gem "sass-rails", '~> 4.0.5'
gem "coffee-rails", '~> 4.1.0'
gem "uglifier", '~> 2.7.2'
gem 'turbolinks', '~> 2.5.0'
gem 'jquery-turbolinks', '~> 2.0.1'
gem 'jquery-turbolinks', '~> 2.1.0'
gem 'addressable', '~> 2.3.8'
gem 'bootstrap-sass', '~> 3.0'
gem 'font-awesome-rails', '~> 4.2'
gem 'gitlab_emoji', '~> 0.1'
gem 'gon', '~> 5.0.0'
gem 'gon', '~> 6.0.1'
gem 'jquery-atwho-rails', '~> 1.3.2'
gem 'jquery-rails', '~> 3.1.3'
gem 'jquery-scrollto-rails', '~> 1.4.3'
......@@ -218,6 +222,7 @@ group :development do
gem 'rerun', '~> 0.10.0'
gem 'bullet', require: false
gem 'rblineprof', platform: :mri, require: false
gem 'web-console', '~> 2.0'
# Better errors handler
gem 'better_errors', '~> 1.0.1'
......@@ -274,7 +279,7 @@ group :test do
gem 'shoulda-matchers', '~> 2.8.0', require: false
gem 'email_spec', '~> 1.6.0'
gem 'webmock', '~> 1.21.0'
gem 'test_after_commit', '~> 0.2.2'
gem 'test_after_commit', '~> 0.4.2'
gem 'sham_rack'
end
......
This diff is collapsed.
......@@ -44,6 +44,7 @@ Workflow labels are purposely not very detailed since that would be hard to keep
- *UX* needs needs help from a UX designer
- *Frontend* needs help from a Front-end engineer
- *Graphics* needs help from a Graphics designer
- *up-for-grabs* is an issue suitable for first-time contributors, of reasonable difficulty and size. Not exclusive with other labels.
Example workflow: when a UX designer provided a design but it needs frontend work they remove the UX label and add the frontend label.
......
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 mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default
worker: bundle exec sidekiq -q post_receive -q mailer -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q mailers -q default
# mail_room: bundle exec mail_room -q -c config/mail_room.yml
app/assets/images/icon-link.png

726 Bytes | W: | H:

app/assets/images/icon-link.png

1.1 KB | W: | H:

app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
app/assets/images/icon-link.png
  • 2-up
  • Swipe
  • Onion skin
#= require clipboard
$ ->
clipboard = new Clipboard '.js-clipboard-trigger',
text: (trigger) ->
$target = $(trigger.nextElementSibling || trigger.previousElementSibling)
$target.data('clipboard-text') || $target.text().trim()
genericSuccess = (e) ->
showTooltip(e.trigger, 'Copied!')
# Clear the selection and blur the trigger so it loses its border
e.clearSelection()
$(e.trigger).blur()
clipboard.on 'success', (e) ->
$(e.trigger).
tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
# Safari doesn't support `execCommand`, so instead we inform the user to
# copy manually.
#
# See http://clipboardjs.com/#browser-support
genericError = (e) ->
if /Mac/i.test(navigator.userAgent)
key = '&#8984;' # Command
else
key = 'Ctrl'
# Clear the selection and blur the trigger so it loses its border
e.clearSelection()
$(e.trigger).blur()
showTooltip(e.trigger, "Press #{key}-C to copy")
# Safari doesn't support `execCommand`, so instead we inform the user to
# copy manually.
#
# See http://clipboardjs.com/#browser-support
clipboard.on 'error', (e) ->
if /Mac/i.test(navigator.userAgent)
title = "Press &#8984;-C to copy"
else
title = "Press Ctrl-C to copy"
showTooltip = (target, title) ->
$(target).
tooltip(
container: 'body'
html: 'true'
placement: 'auto bottom'
title: title
trigger: 'manual'
).
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
$(e.trigger).
tooltip(trigger: 'manual', placement: 'auto bottom', html: true, title: title).
tooltip('show').
one('mouseleave', -> $(this).tooltip('hide'))
$ ->
clipboard = new Clipboard '[data-clipboard-target], [data-clipboard-text]'
clipboard.on 'success', genericSuccess
clipboard.on 'error', genericError
#= require markdown_preview
class @DropzoneInput
constructor: (form) ->
Dropzone.autoDiscover = false
......@@ -11,17 +13,14 @@ class @DropzoneInput
uploadProgress = $("<div class=\"div-dropzone-progress\"></div>")
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_uploads_path = window.project_uploads_path or null
markdown_preview_path = window.markdown_preview_path or null
max_file_size = gon.max_file_size or 10
form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>"
form_textarea.on 'paste', (event) =>
handlePaste(event)
form_textarea.on "input", ->
hideReferencedUsers()
form_textarea.on "blur", ->
renderMarkdown()
$(form).setupMarkdownPreview()
form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper"
......@@ -34,42 +33,6 @@ class @DropzoneInput
"opacity": 0
"display": "none"
# Preview button
$(document).off "click", ".js-md-preview-button"
$(document).on "click", ".js-md-preview-button", (e) ->
###
Shows the Markdown preview.
Lets the server render GFM into Html and displays it.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().removeClass "active"
form.find(".js-md-preview-button").parent().addClass "active"
# toggle content
form.find(".md-write-holder").hide()
form.find(".md-preview-holder").show()
renderMarkdown()
# Write button
$(document).off "click", ".js-md-write-button"
$(document).on "click", ".js-md-write-button", (e) ->
###
Shows the Markdown textarea.
###
e.preventDefault()
form = $(this).closest("form")
# toggle tabs
form.find(".js-md-write-button").parent().addClass "active"
form.find(".js-md-preview-button").parent().removeClass "active"
# toggle content
form.find(".md-write-holder").show()
form.find(".md-preview-holder").hide()
dropzone = form_dropzone.dropzone(
url: project_uploads_path
dictDefaultMessage: ""
......@@ -136,41 +99,6 @@ class @DropzoneInput
child = $(dropzone[0]).children("textarea")
hideReferencedUsers = ->
referencedUsers = form.find(".referenced-users")
referencedUsers.hide()
renderReferencedUsers = (users) ->
referencedUsers = form.find(".referenced-users")
if referencedUsers.length
if users.length >= 10
referencedUsers.show()
referencedUsers.find(".js-referenced-users-count").text users.length
else
referencedUsers.hide()
renderMarkdown = ->
preview = form.find(".js-md-preview")
mdText = form.find(".markdown-area").val()
if mdText.trim().length is 0
preview.text "Nothing to preview."
hideReferencedUsers()
else
preview.text "Loading..."
$.ajax(
type: "POST",
url: markdown_preview_path,
data: {
text: mdText
},
dataType: "json"
).success (data) ->
preview.html data.body
preview.syntaxHighlight()
renderReferencedUsers data.references.users
formatLink = (link) ->
text = "[#{link.alt}](#{link.url})"
text = "!#{text}" if link.is_image
......
# MarkdownPreview
#
# Handles toggling the "Write" and "Preview" tab clicks, rendering the preview,
# and showing a warning when more than `x` users are referenced.
#
class @MarkdownPreview
# Minimum number of users referenced before triggering a warning
referenceThreshold: 10
showPreview: (form) ->
preview = form.find('.js-md-preview')
mdText = form.find('textarea.markdown-area').val()
if mdText.trim().length == 0
preview.text('Nothing to preview.')
@hideReferencedUsers(form)
else
preview.text('Loading...')
@renderMarkdown mdText, (response) =>
preview.html(response.body)
preview.syntaxHighlight()
@renderReferencedUsers(response.references.users, form)
renderMarkdown: (text, success) ->
return unless window.markdown_preview_path
$.ajax
type: 'POST'
url: window.markdown_preview_path
data: { text: text }
dataType: 'json'
success: success
hideReferencedUsers: (form) ->
referencedUsers = form.find('.referenced-users')
referencedUsers.hide()
renderReferencedUsers: (users, form) ->
referencedUsers = form.find('.referenced-users')
if referencedUsers.length
if users.length >= @referenceThreshold
referencedUsers.show()
referencedUsers.find('.js-referenced-users-count').text(users.length)
else
referencedUsers.hide()
markdownPreview = new MarkdownPreview()
previewButtonSelector = '.js-md-preview-button'
writeButtonSelector = '.js-md-write-button'
$.fn.setupMarkdownPreview = ->
$form = $(this)
form_textarea = $form.find('textarea.markdown-area')
form_textarea.on 'input', -> markdownPreview.hideReferencedUsers($form)
form_textarea.on 'blur', -> markdownPreview.showPreview($form)
$(document).on 'click', previewButtonSelector, (e) ->
e.preventDefault()
$form = $(this).closest('form')
# toggle tabs
$form.find(writeButtonSelector).parent().removeClass('active')
$form.find(previewButtonSelector).parent().addClass('active')
# toggle content
$form.find('.md-write-holder').hide()
$form.find('.md-preview-holder').show()
markdownPreview.showPreview($form)
$(document).on 'click', writeButtonSelector, (e) ->
e.preventDefault()
$form = $(this).closest('form')
# toggle tabs
$form.find(writeButtonSelector).parent().addClass('active')
$form.find(previewButtonSelector).parent().removeClass('active')
# toggle content
$form.find('.md-write-holder').show()
$form.find('.md-preview-holder').hide()
class @Project
constructor: ->
# Git clone panel switcher
cloneHolder = $('.git-clone-holder')
if cloneHolder.length
$('a, button', cloneHolder).click ->
$('a, button', cloneHolder).removeClass 'active'
$(@).addClass 'active'
$('#project_clone', cloneHolder).val $(@).data 'clone'
$(".clone").text("").append $(@).data 'clone'
# Git protocol switcher
$('.js-protocol-switch').click ->
return if $(@).hasClass('active')
# Toggle 'active' for both buttons
$('.js-protocol-switch').toggleClass('active')
url = $(@).data('clone')
# Update the input field
$('#project_clone').val(url)
# Update the command line instructions
$('.clone').text(url)
# Ref switcher
$('.project-refs-select').on 'change', ->
......@@ -39,4 +45,4 @@ class @Project
when 4 then label = ' On Mention '
$('#notifications-button').empty().append("<i class='fa fa-bell'></i>" + label + "<i class='fa fa-angle-down'></i>")
$(@).parents('ul').find('li.active').removeClass 'active'
$(@).parent().addClass 'active'
\ No newline at end of file
$(@).parent().addClass 'active'
@import "framework/fonts";
@import "framework/variables";
@import "framework/mixins";
@import "framework/layout";
@import 'framework/tw_bootstrap_variables';
@import 'framework/tw_bootstrap';
@import "framework/layout";
@import "framework/avatar.scss";
@import "framework/blocks.scss";
......@@ -25,6 +25,7 @@
@import "framework/markdown_area.scss";
@import "framework/mobile.scss";
@import "framework/pagination.scss";
@import "framework/panels.scss";
@import "framework/selects.scss";
@import "framework/sidebar.scss";
@import "framework/tables.scss";
......
......@@ -68,6 +68,10 @@
.oneline {
line-height: 42px;
}
> p:last-child {
margin-bottom: 0;
}
}
.cover-block {
......@@ -114,3 +118,7 @@
right: 10px;
}
}
.block-connector {
margin-top: -1px;
}
......@@ -7,7 +7,7 @@
/** COMMON CLASSES **/
.prepend-top-10 { margin-top:10px }
.prepend-top-default { margin-top: $gl-padding; }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-20 { margin-left:20px }
......@@ -52,6 +52,10 @@ pre {
}
}
hr {
margin: $gl-padding 0;
}
.dropdown-menu > li > a {
text-shadow: none;
}
......@@ -442,3 +446,7 @@ table {
.space-right {
margin-right: 10px;
}
.alert, .progress {
margin-bottom: $gl-padding;
}
......@@ -8,7 +8,6 @@
border: none;
border-top: 1px solid #E7E9EE;
border-bottom: 1px solid #E7E9EE;
margin-bottom: 1em;
&.readme-holder {
border-bottom: 0;
......@@ -25,7 +24,7 @@
text-shadow: 0 1px 1px #fff;
margin: 0;
text-align: left;
padding: 10px 15px;
padding: 10px $gl-padding;
.file-actions {
float: right;
......@@ -171,4 +170,3 @@
}
}
}
......@@ -22,9 +22,10 @@ input[type='text'].danger {
}
.form-actions {
padding: 17px 20px 18px;
margin-top: 18px;
margin-bottom: 18px;
margin: -$gl-padding;
margin-top: 0;
margin-bottom: -$gl-padding;
padding: $gl-padding;
background-color: $background-color;
border-top: 1px solid $border-color;
}
......@@ -73,6 +74,8 @@ label {
.form-control {
@include box-shadow(none);
height: 42px;
padding: 8px $gl-padding;
}
.wiki-content {
......@@ -92,3 +95,7 @@ label {
background-color: #f7f8fa;
}
}
.help-block {
margin-bottom: 0;
}
......@@ -7,8 +7,9 @@
.issue-box {
@include border-radius(2px);
display: inline-block;
padding: 10px $gl-padding;
display: block;
float: left;
padding: 0 $gl-padding;
font-weight: normal;
margin-right: 10px;
font-size: $gl-font-size;
......
......@@ -2,10 +2,10 @@ html {
overflow-y: scroll;
&.touch .tooltip { display: none !important; }
}
body {
padding-top: $header-height;
}
body {
background-color: #EAEBEC !important;
}
.container {
......@@ -18,6 +18,7 @@ html {
}
.navless-container {
padding-top: $header-height;
margin-top: 30px;
}
......
......@@ -127,3 +127,8 @@ ul.content-list {
}
}
.panel > .content-list {
li {
margin: 0;
}
}
......@@ -32,3 +32,7 @@
}
}
}
.panel > .gl-pagination {
margin: 0;
}
.panel {
margin-bottom: $gl-padding;
.panel-heading {
padding: 10px $gl-padding;
}
.panel-body {
padding: $gl-padding;
.form-actions {
margin: -$gl-padding;
margin-top: $gl-padding;
}
}
}
.page-with-sidebar {
padding-top: $header-height;
.sidebar-wrapper {
position: fixed;
top: 0;
......@@ -18,15 +20,12 @@
}
.content-wrapper {
min-height: 100vh;
width: 100%;
padding: 20px;
background: #EAEBEC;
.container-fluid {
background: #FFF;
padding: $gl-padding;
min-height: 90vh;
&.container-blank {
background: none;
......
......@@ -6,6 +6,8 @@
table {
&.table {
margin-bottom: $gl-padding;
.dropdown-menu a {
text-decoration: none;
}
......
......@@ -181,6 +181,10 @@ body {
line-height: 1.3;
font-size: 1.25em;
font-weight: 600;
&:last-child {
margin-bottom: 0;
}
}
.page-title-empty {
......@@ -256,3 +260,9 @@ textarea.js-gfm-input {
.strikethrough {
text-decoration: line-through;
}
h1, h2, h3, h4 {
small {
color: $gl-gray;
}
}
......@@ -2,10 +2,6 @@
display: block;
}
.commit-title{
margin-bottom: 10px;
}
.commit-author, .commit-committer{
display: block;
color: #999;
......@@ -41,6 +37,8 @@
.commit-box {
.commit-title {
margin: 0;
font-size: 23px;
color: #313236;
}
.commit-description {
......@@ -108,16 +106,3 @@
z-index: 2;
}
}
.commit-ci-menu {
padding: 0;
margin: 0;
list-style: none;
margin-top: 5px;
height: 56px;
margin: -16px;
padding: 16px;
text-align: center;
margin-top: 0px;
margin-bottom: 2px;
}
......@@ -19,48 +19,38 @@
color: #B94A48;
}
}
.commit-button-annotation {
display: inline-block;
margin: 0;
padding: 2px;
> * {
float: left;
}
.message {
display: inline-block;
margin: 5px 8px 0 8px;
}
}
.file-title {
@extend .monospace;
line-height: 42px;
padding-top: 7px;
padding-bottom: 7px;
}
.editor-ref {
background: $background-color;
padding: 11px 15px;
padding-right: $gl-padding;
border-right: 1px solid $border-color;
display: inline-block;
margin: -5px -5px;
display: block;
float: left;
margin-right: 10px;
}
.editor-file-name {
.new-file-name {
display: inline-block;
width: 450px;
}
@extend .monospace;
float: left;
margin-right: 10px;
}
.form-control {
margin-top: -3px;
}
.new-file-name {
display: inline-block;
width: 450px;
float: left;
}
.form-actions {
margin: -$gl-padding;
margin-top: 0;
padding: $gl-padding
.select2 {
float: right;
}
}
.new-group-member-holder {
margin-top: 50px;
padding-top: 20px;
}
.member-search-form {
float: left;
}
......@@ -15,4 +10,4 @@
.form-control {
height: 42px;
}
}
\ No newline at end of file
}
......@@ -51,11 +51,12 @@
.issuable-details {
.page-title {
margin-top: -15px;
padding: 10px 0;
margin-top: -$gl-padding;
padding: 7px 0;
margin-bottom: 0;
color: #5c5d5e;
font-size: 16px;
line-height: 42px;
.author {
color: #5c5d5e;
......
/* Login Page */
.login-page {
background-color: white;
.container {
max-width: 960px;
}
......
......@@ -4,7 +4,6 @@
*/
.mr-state-widget {
background: #F7F8FA;
margin-bottom: 20px;
color: $gl-gray;
border: 1px solid #dce0e6;
@include border-radius(2px);
......@@ -87,7 +86,7 @@
.mr-widget-body,
.ci_widget,
.mr-widget-footer {
padding: 15px;
padding: $gl-padding;
}
.normal {
......@@ -116,26 +115,8 @@
}
}
.merge-request .merge-request-tabs {
@include nav-menu;
margin: -$gl-padding;
padding: $gl-padding;
text-align: center;
margin-bottom: 1px;
}
// Mobile
@media (max-width: 480px) {
.merge-request .merge-request-tabs {
margin: 0;
padding: 0;
li {
a {
padding: 0;
}
}
}
.merge-request-details {
margin-bottom: $gl-padding;
}
.mr_source_commit,
......
......@@ -7,6 +7,7 @@
}
.reply-btn {
@extend .btn-primary;
margin: 10px $gl-padding;
}
.diff-file .diff-content {
tr.line_holder:hover {
......@@ -38,9 +39,8 @@
}
.new_note, .edit_note {
.buttons {
margin-top: 8px;
margin-bottom: 3px;
.note-form-actions {
margin-top: $gl-padding;
}
.note-preview-holder {
......@@ -79,8 +79,8 @@
padding: $gl-padding;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
border-right: 1px solid #ECEEF1;
border-top: 1px solid #ECEEF1;
border-right: 1px solid $border-color;
border-top: 1px solid $border-color;
margin-bottom: -$gl-padding;
}
......@@ -150,7 +150,6 @@
.discussion-reply-holder {
background: $background-color;
padding: 10px 15px;
border-top: 1px solid $border-color;
}
}
......
......@@ -18,10 +18,6 @@
}
}
.project-edit-content {
padding: 7px;
}
.project-name-holder {
.help-inline {
vertical-align: top;
......@@ -30,12 +26,6 @@
}
.project-home-panel {
text-align: center;
background: #f7f8fa;
margin: -$gl-padding;
padding: $gl-padding;
padding: 44px 0 17px 0;
.project-identicon-holder {
margin-bottom: 16px;
......@@ -90,7 +80,12 @@
}
.visibility-level-label {
@extend .btn;
@extend .btn-gray;
color: $gray;
cursor: auto;
i {
color: inherit;
}
......@@ -100,7 +95,6 @@
display: inline-table;
position: relative;
top: 17px;
margin-bottom: 44px;
}
.project-repo-buttons {
......@@ -178,6 +172,11 @@
&:active {
outline: none;
}
&.btn-clipboard {
padding-left: 15px;
padding-right: 15px;
}
}
.active {
......@@ -370,7 +369,7 @@ table.table.protected-branches-list tr.no-border {
.project-stats {
text-align: center;
margin-top: 15px;
margin-top: $gl-padding;
margin-bottom: 0;
padding-top: 10px;
padding-bottom: 4px;
......@@ -556,4 +555,4 @@ pre.light-well {
z-index: 100;
position: relative;
}
}
\ No newline at end of file
}
......@@ -27,56 +27,22 @@
}
.snippet-holder {
.snippet-details {
.page-title {
margin-top: -15px;
padding: 10px 0;
margin-bottom: 0;
color: #5c5d5e;
font-size: 16px;
.author {
color: #5c5d5e;
}
.snippet-id {
color: #5c5d5e;
}
}
.snippet-title {
margin: 0;
font-size: 23px;
color: #313236;
}
@media (max-width: $screen-md-max) {
.new-snippet-link {
display: none;
}
}
@media (max-width: $screen-sm-max) {
.creator,
.page-title .btn-close {
display: none;
}
}
}
margin-bottom: -$gl-padding;
.file-holder {
border-top: 0;
}
}
.snippet-box {
@include border-radius(2px);
display: inline-block;
padding: 10px $gl-padding;
display: block;
float: left;
padding: 0 $gl-padding;
font-weight: normal;
margin-right: 10px;
font-size: $gl-font-size;
border: 1px solid;
line-height: 40px;
}
......@@ -10,7 +10,7 @@ class AbuseReportsController < ApplicationController
if @abuse_report.save
if current_application_settings.admin_notification_email.present?
AbuseReportMailer.delay.notify(@abuse_report.id)
AbuseReportMailer.notify(@abuse_report.id).deliver_later
end
message = "Thank you for your report. A GitLab administrator will look into it shortly."
......
......@@ -5,14 +5,20 @@ class Admin::ImpersonationController < Admin::ApplicationController
before_action :authorize_impersonator!
def create
session[:impersonator_id] = current_user.username
session[:impersonator_return_to] = request.env['HTTP_REFERER']
if @user.blocked?
flash[:alert] = "You cannot impersonate a blocked user"
warden.set_user(user, scope: 'user')
redirect_to admin_user_path(@user)
else
session[:impersonator_id] = current_user.username
session[:impersonator_return_to] = admin_user_path(@user)
warden.set_user(user, scope: 'user')
flash[:alert] = "You are impersonating #{user.username}."
flash[:alert] = "You are impersonating #{user.username}."
redirect_to root_path
redirect_to root_path
end
end
def destroy
......
......@@ -14,7 +14,7 @@ class AutocompleteController < ApplicationController
@users = @users.page(params[:page]).per(PER_PAGE)
end
unless params[:search].present?
if params[:search].blank?
# Include current user if available to filter by "Me"
if params[:current_user] && current_user
@users = [*@users, current_user].uniq
......
......@@ -67,7 +67,12 @@ class Projects::CommitController < Projects::ApplicationController
end
def define_show_vars
@diffs = commit.diffs
if params[:w].to_i == 1
@diffs = commit.diffs({ ignore_whitespace_change: true })
else
@diffs = commit.diffs
end
@notes_count = commit.notes.count
@builds = ci_commit.builds if ci_commit
......
......@@ -164,12 +164,10 @@ class Projects::IssuesController < Projects::ApplicationController
end
def issue_params
permitted = params.require(:issue).permit(
params.require(:issue).permit(
:title, :assignee_id, :position, :description,
:milestone_id, :state_event, :task_num, label_ids: []
)
params[:issue][:title].strip! if params[:issue][:title]
permitted
end
def bulk_update_params
......
......@@ -325,13 +325,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def merge_request_params
permitted = params.require(:merge_request).permit(
params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :approver_ids,
:state_event, :description, :task_num, label_ids: []
)
params[:merge_request][:title].strip! if params[:merge_request][:title]
permitted
end
# Make sure merge requests created before 8.0
......
......@@ -124,7 +124,7 @@ class ProjectsController < ApplicationController
::Projects::DestroyService.new(@project, current_user, {}).execute
flash[:alert] = "Project '#{@project.name}' was deleted."
redirect_back_or_default(default: dashboard_projects_path, options: {})
redirect_to dashboard_projects_path
rescue Projects::DestroyService::DestroyError => ex
redirect_to edit_project_path(@project), alert: ex.message
end
......
......@@ -2,7 +2,7 @@ class SnippetsController < ApplicationController
before_action :snippet, only: [:show, :edit, :destroy, :update, :raw]
# Allow read snippet
before_action :authorize_read_snippet!, only: [:show]
before_action :authorize_read_snippet!, only: [:show, :raw]
# Allow modify snippet
before_action :authorize_update_snippet!, only: [:edit, :update]
......
......@@ -11,7 +11,7 @@ class UnsubscribesController < ApplicationController
@user = get_user
if @user
@user.admin_unsubscribe!
Notify.send_unsubscribed_notification(@user).deliver
Notify.send_unsubscribed_notification(@user.id).deliver_later
end
redirect_to new_user_session_path, notice: 'You have been unsubscribed'
end
......
......@@ -68,7 +68,7 @@ module ApplicationHelper
end
end
def avatar_icon(user_or_email = nil, size = nil)
def avatar_icon(user_or_email = nil, size = nil, scale = 2)
if user_or_email.is_a?(User)
user = user_or_email
else
......@@ -78,12 +78,12 @@ module ApplicationHelper
if user
user.avatar_url(size) || default_avatar
else
gravatar_icon(user_or_email, size)
gravatar_icon(user_or_email, size, scale)
end
end
def gravatar_icon(user_email = '', size = nil)
GravatarService.new.execute(user_email, size) ||
def gravatar_icon(user_email = '', size = nil, scale = 2)
GravatarService.new.execute(user_email, size, scale) ||
default_avatar
end
......
......@@ -60,7 +60,7 @@ module BlobHelper
if Gitlab::MarkupHelper.previewable?(filename)
'Preview'
else
'Preview changes'
'Preview Changes'
end
end
......
module ButtonHelper
# Output a "Copy to Clipboard" button
#
# data - Data attributes passed to `content_tag`
#
# Examples:
#
# # Define the clipboard's text
# clipboard_button(clipboard_text: "Foo")
# # => "<button class='...' data-clipboard-text='Foo'>...</button>"
#
# # Define the target element
# clipboard_button(clipboard_target: "#foo")
# # => "<button class='...' data-clipboard-target='#foo'>...</button>"
#
# See http://clipboardjs.com/#usage
def clipboard_button(data = {})
content_tag :button,
icon('clipboard'),
class: 'btn btn-xs btn-clipboard',
data: data,
type: :button
end
def http_clone_button(project)
klass = 'btn js-protocol-switch'
klass << ' active' if default_clone_protocol == 'http'
klass << ' has_tooltip' if current_user.try(:require_password?)
protocol = gitlab_config.protocol.upcase
content_tag :button, protocol,
class: klass,
data: {
clone: project.http_url_to_repo,
container: 'body',
html: 'true',
title: "Set a password on your account<br>to pull or push via #{protocol}"
},
type: :button
end
def ssh_clone_button(project)
klass = 'btn js-protocol-switch'
klass << ' active' if default_clone_protocol == 'ssh'
klass << ' has_tooltip' if current_user.try(:require_ssh_key?)
content_tag :button, 'SSH',
class: klass,
data: {
clone: project.ssh_url_to_repo,
container: 'body',
html: 'true',
title: 'Add an SSH key to your profile<br>to pull or push via SSH.'
},
type: :button
end
end
module ClipboardHelper
def clipboard_button
content_tag :button,
icon('clipboard'),
class: 'btn btn-xs btn-clipboard js-clipboard-trigger',
type: :button
end
end
......@@ -109,7 +109,7 @@ module CommitsHelper
)
elsif @path.present?
return link_to(
"Browse Dir »",
"Browse Directory »",
namespace_project_tree_path(project.namespace, project,
tree_join(commit.id, @path)),
class: "pull-right"
......@@ -117,7 +117,7 @@ module CommitsHelper
end
end
link_to(
"Browse Code »",
"Browse Files »",
namespace_project_tree_path(project.namespace, project, commit),
class: "pull-right"
)
......
......@@ -146,9 +146,9 @@ module DiffHelper
def submodule_link(blob, ref, repository = @repository)
tree, commit = submodule_links(blob, ref, repository)
commit_id = if commit.nil?
blob.id[0..10]
Commit.truncate_sha(blob.id)
else
link_to "#{blob.id[0..10]}", commit
link_to Commit.truncate_sha(blob.id), commit
end
[
......
......@@ -28,6 +28,8 @@ module EmailsHelper
return "View #{action.humanize.singularize}"
end
end
nil
end
def color_email_diff(diffcontent)
......
......@@ -173,8 +173,7 @@ module ProjectsHelper
'unknown'
end
def default_url_to_repo(project = nil)
project = project || @project
def default_url_to_repo(project = @project)
current_user ? project.url_to_repo : project.http_url_to_repo
end
......
......@@ -8,10 +8,6 @@ class BaseMailer < ActionMailer::Base
default from: Proc.new { default_sender_address.format }
default reply_to: Proc.new { default_reply_to_address.format }
def self.delay
delay_for(2.seconds)
end
def can?
Ability.abilities.allowed?(current_user, action, subject)
end
......
......@@ -74,15 +74,23 @@ class ApplicationSetting < ActiveRecord::Base
end
after_commit do
Rails.cache.write('application_setting.last', self)
Rails.cache.write(cache_key, self)
end
def self.current
Rails.cache.fetch('application_setting.last') do
Rails.cache.fetch(cache_key) do
ApplicationSetting.last
end
end
def self.expire
Rails.cache.delete(cache_key)
end
def self.cache_key
'application_setting.last'
end
def self.create_from_defaults
create(
default_projects_limit: Settings.gitlab['default_projects_limit'],
......
......@@ -14,11 +14,15 @@ module Ci
extend Ci::Model
after_commit do
Rails.cache.write('ci_application_setting.last', self)
Rails.cache.write(cache_key, self)
end
def self.expire
Rails.cache.delete(cache_key)
end
def self.current
Rails.cache.fetch('ci_application_setting.last') do
Rails.cache.fetch(cache_key) do
Ci::ApplicationSetting.last
end
end
......@@ -29,5 +33,9 @@ module Ci
add_pusher: Settings.gitlab_ci['add_pusher'],
)
end
def self.cache_key
'ci_application_setting.last'
end
end
end
......@@ -8,6 +8,7 @@ module Issuable
extend ActiveSupport::Concern
include Participable
include Mentionable
include StripAttribute
included do
belongs_to :author, class_name: "User"
......@@ -51,6 +52,7 @@ module Issuable
attr_mentionable :title, :description
participant :author, :assignee, :notes_with_associations
strip_attributes :title
end
module ClassMethods
......
# == Strip Attribute module
#
# Contains functionality to clean attributes before validation
#
# Usage:
#
# class Milestone < ActiveRecord::Base
# strip_attributes :title
# end
#
#
module StripAttribute
extend ActiveSupport::Concern
module ClassMethods
def strip_attributes(*attrs)
strip_attrs.concat(attrs)
end
def strip_attrs
@strip_attrs ||= []
end
end
included do
before_validation :strip_attributes
end
def strip_attributes
self.class.strip_attrs.each do |attr|
self[attr].strip! if self[attr] && self[attr].respond_to?(:strip!)
end
end
end
class HistoricalData < ActiveRecord::Base
validate :date, presence: true
validates :date, presence: true
# HistoricalData.during((Date.today - 1.year)..Date.today).average(:active_user_count)
scope :during, ->(range) { where(date: range) }
......
......@@ -22,6 +22,7 @@ class Milestone < ActiveRecord::Base
include InternalId
include Sortable
include StripAttribute
belongs_to :project
has_many :issues
......@@ -35,6 +36,8 @@ class Milestone < ActiveRecord::Base
validates :title, presence: true
validates :project, presence: true
strip_attributes :title
state_machine :state, initial: :active do
event :close do
transition active: :closed
......
......@@ -44,7 +44,6 @@ class Project < ActiveRecord::Base
include CaseSensitivity
extend Gitlab::ConfigHelper
extend Enumerize
UNKNOWN_IMPORT_URL = 'http://unknown.git'
......
......@@ -37,7 +37,7 @@ class BuildkiteService < CiService
def compose_service_hook
hook = service_hook || build_service_hook
hook.url = webhook_url
hook.enable_ssl_verification = enable_ssl_verification
hook.enable_ssl_verification = !!enable_ssl_verification
hook.save
end
......
......@@ -64,9 +64,9 @@ module Ci
build.project_recipients.each do |recipient|
case build.status.to_sym
when :success
mailer.build_success_email(build.id, recipient)
mailer.build_success_email(build.id, recipient).deliver_later
when :failed
mailer.build_fail_email(build.id, recipient)
mailer.build_fail_email(build.id, recipient).deliver_later
end
end
end
......@@ -78,7 +78,7 @@ module Ci
end
def mailer
Ci::Notify.delay
Ci::Notify
end
end
end
......@@ -34,7 +34,7 @@ class DroneCiService < CiService
hook = service_hook || build_service_hook
# If using a service template, project may not be available
hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
hook.enable_ssl_verification = enable_ssl_verification
hook.enable_ssl_verification = !!enable_ssl_verification
hook.save
end
......
......@@ -55,7 +55,7 @@ class GitlabCiService < CiService
end
def get_ci_commit(sha, ref)
Ci::Project.find(project.gitlab_ci_project).commits.find_by_sha!(sha)
Ci::Project.find(project.gitlab_ci_project.id).commits.find_by_sha!(sha)
end
def commit_status(sha, ref)
......
......@@ -627,9 +627,13 @@ class Repository
# Run GitLab pre-receive hook
pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', path_to_repo)
status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref)
pre_receive_hook_status = pre_receive_hook.trigger(gl_id, oldrev, newrev, ref)
if status
# Run GitLab update hook
update_hook = Gitlab::Git::Hook.new('update', path_to_repo)
update_hook_status = update_hook.trigger(gl_id, oldrev, newrev, ref)
if pre_receive_hook_status && update_hook_status
if was_empty
# Create branch
rugged.references.create(ref, newrev)
......@@ -652,7 +656,7 @@ class Repository
# Remove tmp ref and return error to user
rugged.references.delete(tmp_ref)
raise PreReceiveError.new('Commit was rejected by pre-receive hook')
raise PreReceiveError.new('Commit was rejected by git hook')
end
end
......
......@@ -17,9 +17,8 @@ class SentNotification < ActiveRecord::Base
belongs_to :noteable, polymorphic: true
belongs_to :recipient, class_name: "User"
validate :project, :recipient, :reply_key, presence: true
validate :reply_key, uniqueness: true
validates :project, :recipient, :reply_key, presence: true
validates :reply_key, uniqueness: true
validates :noteable_id, presence: true, unless: :for_commit?
validates :commit_id, presence: true, if: :for_commit?
validates :line_code, format: { with: /\A[a-z0-9]+_\d+_\d+\Z/ }, allow_blank: true
......
......@@ -665,11 +665,11 @@ class User < ActiveRecord::Base
email.start_with?('temp-email-for-oauth')
end
def avatar_url(size = nil)
def avatar_url(size = nil, scale = 2)
if avatar.present?
[gitlab_config.url, avatar.url].join
else
GravatarService.new.execute(email, size)
GravatarService.new.execute(email, size, scale)
end
end
......@@ -722,7 +722,7 @@ class User < ActiveRecord::Base
end
def starred?(project)
starred_projects.exists?(project)
starred_projects.exists?(project.id)
end
def toggle_star(project)
......@@ -827,4 +827,9 @@ class User < ActiveRecord::Base
Gitlab::SQL::Union.new([personal_projects.select(:id), groups.select(:id),
other.select(:id)])
end
# Added according to https://github.com/plataformatec/devise/blob/7df57d5081f9884849ca15e4fde179ef164a575f/README.md#activejob-integration
def send_devise_notification(notification, *args)
devise_mailer.send(notification, self, *args).deliver_later
end
end
class GravatarService
include Gitlab::CurrentSettings
def execute(email, size = nil)
def execute(email, size = nil, scale = 2)
if current_application_settings.gravatar_enabled? && email.present?
size = 40 if size.nil? || size <= 0
sprintf gravatar_url,
hash: Digest::MD5.hexdigest(email.strip.downcase),
size: size,
size: size * scale,
email: email.strip
end
end
......
......@@ -38,7 +38,7 @@ module MergeRequests
}
repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
rescue Exception => e
rescue StandardError => e
merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message)
return false
......
......@@ -13,14 +13,14 @@ class NotificationService
# even if user disabled notifications
def new_key(key)
if key.user
mailer.new_ssh_key_email(key.id)
mailer.new_ssh_key_email(key.id).deliver_later
end
end
# Always notify user about email added to profile
def new_email(email)
if email.user
mailer.new_email_email(email.id)
mailer.new_email_email(email.id).deliver_later
end
end
......@@ -79,17 +79,27 @@ class NotificationService
end
def merge_mr(merge_request, current_user)
close_resource_email(merge_request, merge_request.target_project, current_user, 'merged_merge_request_email')
close_resource_email(
merge_request,
merge_request.target_project,
current_user,
'merged_merge_request_email'
)
end
def reopen_mr(merge_request, current_user)
reopen_resource_email(merge_request, merge_request.target_project, current_user, 'merge_request_status_email', 'reopened')
reopen_resource_email(
merge_request,
merge_request.target_project,
current_user, 'merge_request_status_email',
'reopened'
)
end
# Notify new user with email after creation
def new_user(user, token = nil)
# Don't email omniauth created users
mailer.new_user_email(user.id, token) unless user.identities.any?
mailer.new_user_email(user.id, token).deliver_later unless user.identities.any?
end
# Notify users on new note in system
......@@ -138,50 +148,59 @@ class NotificationService
# build notify method like 'note_commit_email'
notify_method = "note_#{note.noteable_type.underscore}_email".to_sym
recipients.each do |recipient|
mailer.send(notify_method, recipient.id, note.id)
mailer.send(notify_method, recipient.id, note.id).deliver_later
end
end
def invite_project_member(project_member, token)
mailer.project_member_invited_email(project_member.id, token)
mailer.project_member_invited_email(project_member.id, token).deliver_later
end
def accept_project_invite(project_member)
mailer.project_invite_accepted_email(project_member.id)
mailer.project_invite_accepted_email(project_member.id).deliver_later
end
def decline_project_invite(project_member)
mailer.project_invite_declined_email(project_member.project.id, project_member.invite_email, project_member.access_level, project_member.created_by_id)
mailer.project_invite_declined_email(
project_member.project.id,
project_member.invite_email,
project_member.access_level,
project_member.created_by_id
).deliver_later
end
def new_project_member(project_member)
mailer.project_access_granted_email(project_member.id)
mailer.project_access_granted_email(project_member.id).deliver_later
end
def update_project_member(project_member)
mailer.project_access_granted_email(project_member.id)
mailer.project_access_granted_email(project_member.id).deliver_later
end
def invite_group_member(group_member, token)
mailer.group_member_invited_email(group_member.id, token)
mailer.group_member_invited_email(group_member.id, token).deliver_later
end
def accept_group_invite(group_member)
mailer.group_invite_accepted_email(group_member.id)
mailer.group_invite_accepted_email(group_member.id).deliver_later
end
def decline_group_invite(group_member)
mailer.group_invite_declined_email(group_member.group.id, group_member.invite_email, group_member.access_level, group_member.created_by_id)
mailer.group_invite_declined_email(
group_member.group.id,
group_member.invite_email,
group_member.access_level,
group_member.created_by_id
).deliver_later
end
def new_group_member(group_member)
mailer.group_access_granted_email(group_member.id)
mailer.group_access_granted_email(group_member.id).deliver_later
end
def update_group_member(group_member)
mailer.group_access_granted_email(group_member.id)
mailer.group_access_granted_email(group_member.id).deliver_later
end
def project_was_moved(project, old_path_with_namespace)
......@@ -189,7 +208,11 @@ class NotificationService
recipients = reject_muted_users(recipients, project)
recipients.each do |recipient|
mailer.project_was_moved_email(project.id, recipient.id, old_path_with_namespace)
mailer.project_was_moved_email(
project.id,
recipient.id,
old_path_with_namespace
).deliver_later
end
end
......@@ -339,7 +362,7 @@ class NotificationService
recipients = build_recipients(target, project, target.author)
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id)
mailer.send(method, recipient.id, target.id).deliver_later
end
end
......@@ -347,7 +370,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user)
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, current_user.id)
mailer.send(method, recipient.id, target.id, current_user.id).deliver_later
end
end
......@@ -358,7 +381,13 @@ class NotificationService
recipients = build_recipients(target, project, current_user, [previous_assignee])
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, previous_assignee_id, current_user.id)
mailer.send(
method,
recipient.id,
target.id,
previous_assignee_id,
current_user.id
).deliver_later
end
end
......@@ -366,7 +395,7 @@ class NotificationService
recipients = build_recipients(target, project, current_user)
recipients.each do |recipient|
mailer.send(method, recipient.id, target.id, status, current_user.id)
mailer.send(method, recipient.id, target.id, status, current_user.id).deliver_later
end
end
......@@ -388,7 +417,7 @@ class NotificationService
end
def mailer
Notify.delay
Notify
end
def previous_record(object, attribute)
......
......@@ -2,4 +2,4 @@
= render_colored_label(label)
.pull-right
= link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm'
= link_to 'Remove', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
= link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"}
......@@ -6,7 +6,7 @@
%span.cred (Admin)
.pull-right
- unless @user == current_user
- unless @user == current_user || @user.blocked?
= link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-grouped btn-info"
= link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
%i.fa.fa-pencil-square-o
......
- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
.panel.panel-default.contributed-projects
.panel-heading Projects contributed to
= render 'shared/projects/list',
projects: contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 5, stars: true, avatar: false
- if local_assigns.has_key?(:projects) && projects.present?
.panel.panel-default
.panel-heading Personal projects
= render 'shared/projects/list',
projects: projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: false
......@@ -14,7 +14,7 @@
.row
.col-md-6
- if @personal_projects.present?
= render 'users/projects', projects: @personal_projects
= render 'admin/users/projects', projects: @personal_projects
- else
.nothing-here-block This user has no personal projects.
......
......@@ -37,7 +37,7 @@
= label_tag :tag_list, class: 'control-label' do
Tags
.col-sm-10
= f.text_field :tag_list, class: 'form-control'
= f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control'
.help-block You can setup builds to only use runners with specific tags
.form-actions
= f.submit 'Save', class: 'btn btn-save'
......
......@@ -7,7 +7,7 @@
= @project.name
%p
Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)}
Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.gl_project.namespace, @build.gl_project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
%p
......
......@@ -8,7 +8,7 @@
= @project.name
%p
Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)}
Commit: #{link_to @build.short_sha, namespace_project_commit_url(@build.gl_project.namespace, @build.gl_project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
%p
......
......@@ -8,8 +8,8 @@
= link_to new_group_path, class: "btn btn-new" do
%i.fa.fa-plus
New Group
.title Welcome to the groups!
Group members have access to all group projects.
.oneline
Group members have access to all group projects.
%ul.content-list
- @group_members.each do |group_member|
......
......@@ -3,7 +3,7 @@
.form-group
= search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false
.form-group
= button_tag 'Search', class: "btn btn-success"
= button_tag 'Search', class: "btn"
.pull-right.hidden-sm.hidden-xs
- if current_user
......
......@@ -4,7 +4,7 @@
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
%span{class: ("list-item-name" if show_controls)}
- if member.user
= image_tag avatar_icon(user, 16), class: "avatar s16", alt: ''
= image_tag avatar_icon(user, 24), class: "avatar s24", alt: ''
%strong
= link_to user.name, user_path(user)
%span.cgray= user.username
......@@ -14,7 +14,7 @@
%label.label.label-danger
%strong Blocked
- else
= image_tag avatar_icon(member.invite_email, 16), class: "avatar s16", alt: ''
= image_tag avatar_icon(member.invite_email, 24), class: "avatar s24", alt: ''
%strong
= member.invite_email
%span.cgray
......@@ -30,7 +30,7 @@
- if should_user_see_group_roles?(current_user, @group)
%span.pull-right
%strong= member.human_access
%strong.member-access-level= member.human_access
- if show_controls
- if can?(current_user, :update_group_member, member)
= button_tag class: "btn-xs btn js-toggle-button",
......
- page_title "Members"
- header_title group_title(@group, "Members", group_group_members_path(@group))
- if should_user_see_group_roles?(current_user, @group)
%p.light
Members of group have access to all group projects.
Read more about permissions
%strong= link_to "here", help_page_path("permissions", "permissions"), class: "vlink"
.clearfix.js-toggle-container
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control search-text-input', spellcheck: false }
= button_tag 'Search', class: 'btn'
- @blank_container = true
.group-members-page
- if current_user && current_user.can?(:admin_group_member, @group)
.pull-right
- if @group.ldap_synced?
.panel.panel-default
.panel-heading
Add new user to group
.panel-body
- if should_user_see_group_roles?(current_user, @group)
%p.light
Members of group have access to all group projects.
.new-group-member-holder
= render "new_group_member"
- if @group.ldap_synced?
.bs-callout.bs-callout-info
The members of this group are managed using LDAP and cannot be added, changed or removed here.
Because LDAP permissions in GitLab get updated one user at a time and because GitLab caches LDAP check results, changes on your LDAP server or in this group's LDAP sync settings may take up to #{Gitlab.config.ldap['sync_time']}s to show in the list below.
%ul
- @group.ldap_group_links.each do |ldap_group_link|
%li
People in cn
%code= ldap_group_link.cn
are given
%code= ldap_group_link.human_access
access.
- if current_user && current_user.can?(:admin_group, @group)
= form_tag(reset_access_group_ldap_path(@group), method: :put, class: 'inline') do
= button_to 'Clear LDAP permission cache', '#', class: "btn btn-remove js-confirm-danger",
data: { "confirm-danger-message" => clear_ldap_permission_cache_message,
'warning-message' => 'If you made manual permission tweaks for some group members they will be lost.' }
= button_tag class: 'btn btn-new js-toggle-button', type: 'button' do
Add members
%i.fa.fa-chevron-down
.js-toggle-content.hide.new-group-member-holder
= render "new_group_member"
- if @group.ldap_synced?
.bs-callout.bs-callout-info
The members of this group are managed using LDAP and cannot be added, changed or removed here.
Because LDAP permissions in GitLab get updated one user at a time and because GitLab caches LDAP check results, changes on your LDAP server or in this group's LDAP sync settings may take up to #{Gitlab.config.ldap['sync_time']}s to show in the list below.
%ul
- @group.ldap_group_links.each do |ldap_group_link|
%li
People in cn
%code= ldap_group_link.cn
are given
%code= ldap_group_link.human_access
access.
.panel.panel-default.prepend-top-20
.panel-heading
%strong #{@group.name}
group members
%small
(#{@members.total_count})
%ul.well-list
- @members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: true
= paginate @members, theme: 'gitlab'
= render 'shared/confirm_modal', phrase: 'reset'
.panel.panel-default
.panel-heading
%strong #{@group.name}
group members
%small
(#{@members.total_count})
.pull-right
= form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do
.form-group
= search_field_tag :search, params[:search], { placeholder: 'Find existing member by name', class: 'form-control', spellcheck: false }
= button_tag class: 'btn', title: 'Search' do
= icon("search")
%ul.content-list
- @members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: true
= paginate @members, theme: 'gitlab'
:javascript
$('form.member-search-form').on('submit', function(event) {
event.preventDefault();
Turbolinks.visit(this.action + '?' + $(this).serialize());
});
= render 'shared/confirm_modal', phrase: 'reset'
- page_title "Bitbucket import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-bitbucket
Import projects from Bitbucket
......
- page_title "FogBugz Import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
......
- page_title 'User map', 'FogBugz import'
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
......
- page_title "FogBugz import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-bug
Import projects from FogBugz
......
- page_title "GitHub import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-github
Import projects from GitHub
......
- page_title "GitLab.com import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-heart
Import projects from GitLab.com
......
- page_title "Gitorious import"
- header_title "Projects", root_path
%h3.page-title
%i.icon-gitorious.icon-gitorious-big
Import projects from Gitorious.org
......
- page_title "Google Code import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-google
Import projects from Google Code
......
- page_title "User map", "Google Code import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-google
Import projects from Google Code
......@@ -8,31 +9,31 @@
%p
Customize how Google Code email addresses and usernames are imported into GitLab.
In the next step, you'll be able to select the projects you want to import.
%p
%p
The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side.
%ul
%li
%strong Default: Directly import the Google Code email address or username
%p
<code>"johnsmith@example.com": "johnsm...@example.com"</code>
will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com.
<code>"johnsmith@example.com": "johnsm...@example.com"</code>
will add "By johnsm...@example.com" to all issues and comments originally created by johnsmith@example.com.
The email address or username is masked to ensure the user's privacy.
%li
%strong Map a Google Code user to a GitLab user
%p
<code>"johnsmith@example.com": "@johnsmith"</code>
will add "By <a href="#">@johnsmith</a>" to all issues and comments originally created by johnsmith@example.com,
<code>"johnsmith@example.com": "@johnsmith"</code>
will add "By <a href="#">@johnsmith</a>" to all issues and comments originally created by johnsmith@example.com,
and will set <a href="#">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com.
%li
%strong Map a Google Code user to a full name
%p
<code>"johnsmith@example.com": "John Smith"</code>
<code>"johnsmith@example.com": "John Smith"</code>
will add "By John Smith" to all issues and comments originally created by johnsmith@example.com.
%li
%strong Map a Google Code user to a full email address
%p
<code>"johnsmith@example.com": "johnsmith@example.com"</code>
will add "By <a href="#">johnsmith@example.com</a>" to all issues and comments originally created by johnsmith@example.com.
<code>"johnsmith@example.com": "johnsmith@example.com"</code>
will add "By <a href="#">johnsmith@example.com</a>" to all issues and comments originally created by johnsmith@example.com.
By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address.
.form-group
......
- page_title "Google Code import"
- header_title "Projects", root_path
%h3.page-title
%i.fa.fa-google
Import projects from Google Code
......
......@@ -5,10 +5,10 @@
%strong= ldap_group_link.cn
- if ldap_group_link.config
%p.light
.light
As #{ldap_group_link.human_access} on #{ldap_group_link.provider_label} server
- else
%p.cred
.cred
%i.fa.fa-warning
Config for
%code #{ldap_group_link.provider}
......
......@@ -15,24 +15,25 @@
.pull-right
= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success'
- if @applications.any?
%table.table.table-striped
%thead
%tr
%th Name
%th Callback URL
%th Clients
%th
%th
%tbody
- @applications.each do |application|
%tr{:id => "application_#{application.id}"}
%td= link_to application.name, oauth_application_path(application)
%td
- application.redirect_uri.split.each do |uri|
%div= uri
%td= application.access_tokens.count
%td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link btn-sm'
%td= render 'doorkeeper/applications/delete_form', application: application
.table-holder
%table.table.table-striped
%thead
%tr
%th Name
%th Callback URL
%th Clients
%th
%th
%tbody
- @applications.each do |application|
%tr{:id => "application_#{application.id}"}
%td= link_to application.name, oauth_application_path(application)
%td
- application.redirect_uri.split.each do |uri|
%div= uri
%td= application.access_tokens.count
%td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link btn-sm'
%td= render 'doorkeeper/applications/delete_form', application: application
.oauth-authorized-applications.prepend-top-20
- if user_oauth_applications?
......@@ -40,29 +41,30 @@
Authorized applications
- if @authorized_tokens.any?
%table.table.table-striped
%thead
%tr
%th Name
%th Authorized At
%th Scope
%th
%tbody
- @authorized_apps.each do |app|
- token = app.authorized_tokens.order('created_at desc').first
%tr{:id => "application_#{app.id}"}
%td= app.name
%td= token.created_at
%td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', application: app
- @authorized_anonymous_tokens.each do |token|
.table-holder
%table.table.table-striped
%thead
%tr
%td
Anonymous
%div.help-block
%em Authorization was granted by entering your username and password in the application.
%td= token.created_at
%td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', token: token
%th Name
%th Authorized At
%th Scope
%th
%tbody
- @authorized_apps.each do |app|
- token = app.authorized_tokens.order('created_at desc').first
%tr{:id => "application_#{app.id}"}
%td= app.name
%td= token.created_at
%td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', application: app
- @authorized_anonymous_tokens.each do |token|
%tr
%td
Anonymous
%div.help-block
%em Authorization was granted by entering your username and password in the application.
%td= token.created_at
%td= token.scopes
%td= render 'doorkeeper/authorized_applications/delete_form', token: token
- else
%p.light You don't have any authorized applications
- is_admin = defined?(admin) ? true : false
.panel.panel-default
- if @keys.any?
- if @keys.any?
.table-holder
%table.table
%thead.panel-heading
%tr
......@@ -11,9 +11,9 @@
%tbody
- @keys.each do |key|
= render 'profiles/keys/key', key: key, is_admin: is_admin
- else
.nothing-here-block
- if is_admin
User has no ssh keys
- else
There are no SSH keys with access to your account.
- else
.nothing-here-block
- if is_admin
User has no ssh keys
- else
There are no SSH keys with access to your account.
......@@ -3,7 +3,9 @@
.gray-content-block.top-block
.pull-right
= link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new"
= link_to new_profile_key_path, class: "btn btn-new" do
= icon('plus')
Add SSH Key
.oneline
Before you can add an SSH key you need to
= link_to "generate it.", help_page_path("ssh", "README")
......
......@@ -50,12 +50,10 @@
Watch
%p You will receive notifications for any activity
.form-actions
.gray-content-block
= f.submit 'Save changes', class: "btn btn-create"
.clearfix
%hr
.row.all-notifications
.row.all-notifications.prepend-top-default
.col-md-6
%p
You can also specify notification level per group or per project.
......
- empty_repo = @project.empty_repo?
.project-home-panel.clearfix{:class => ("empty-project" if empty_repo)}
.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-desc
......@@ -12,6 +12,10 @@
Forked from
= link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name)
.cover-controls
.visibility-level-label
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
- if @project.mirror?
- import_url = @project.safe_import_url
......@@ -27,7 +31,7 @@
= render 'projects/buttons/fork'
= render "shared/clone_panel"
.split-repo-buttons
= render "projects/buttons/update_mirror"
= render "projects/buttons/download"
......
......@@ -5,7 +5,7 @@
%a.js-md-write-button(href="#md-write-holder" tabindex="-1")
Write
%li
%a.js-md-preview-button(href="md-preview-holder" tabindex="-1")
%a.js-md-preview-button(href="#md-preview-holder" tabindex="-1")
Preview
- if defined?(referenced_users) && referenced_users
......
......@@ -7,15 +7,16 @@
= cache(readme_cache_key) do
= render_readme(readme)
- else
%h3.page-title
This project does not have README yet
- if can?(current_user, :push_code, @project)
%p.slead
A
%code README
file contains information about other files in a repository and is commonly
distributed with computer software, forming part of its documentation.
%br
We recommend you to
= link_to "add README", new_readme_path, class: 'underlined-link'
file to the repository and GitLab will render it here instead of this message.
.gray-content-block.second-block.center
%h3.page-title
This project does not have README yet
- if can?(current_user, :push_code, @project)
%p
A
%code README
file contains information about other files in a repository and is commonly
distributed with computer software, forming part of its documentation.
%p
We recommend you to
= link_to "add README", new_readme_path, class: 'underlined-link'
file to the repository and GitLab will render it here instead of this message.
......@@ -6,7 +6,7 @@
#tree-holder.tree-holder
.file-holder
.file-title
%i.fa.fa-file
= blob_icon @blob.mode, @blob.name
%strong
= @path
%small= number_to_human_size @blob.size
......@@ -43,4 +43,3 @@
- blame_group[:lines].each do |line|
:erb
<%= highlight(@blob.name, line, nowrap: true, continue: true).html_safe %>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
File mode changed from 100644 to 100755
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
File mode changed from 100644 to 100755
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment