Commit 96e6cc9c authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream' into 'master'

CE upstream



See merge request !235
parents c8bbbdc7 9a7e3061
......@@ -23,6 +23,7 @@ config/gitlab.yml
config/gitlab_ci.yml
config/initializers/rack_attack.rb
config/initializers/smtp_settings.rb
config/initializers/relative_url.rb
config/resque.yml
config/unicorn.rb
config/secrets.yml
......
......@@ -5,12 +5,32 @@ v 8.6.0 (unreleased)
- Improve the formatting for the user page bio (Connor Shea)
- Fix issue when pushing to projects ending in .wiki
- Fix avatar stretching by providing a cropping feature (Johann Pardanaud)
- Don't load all of GitLab in mail_room
- Strip leading and trailing spaces in URL validator (evuez)
- Return empty array instead of 404 when commit has no statuses in commit status API
- Update documentation to reflect Guest role not being enforced on internal projects
- Allow search for logged out users
- Don't show Issues/MRs from archived projects in Groups view
v 8.5.3
- Flush repository caches before renaming projects
v 8.5.2
- Fix sidebar overlapping content when screen width was below 1200px
- Don't repeat labels listed on Labels tab
- Bring the "branded appearance" feature from EE to CE
- Fix error 500 when commenting on a commit
- Show days remaining instead of elapsed time for Milestone
- Fix broken icons on installations with relative URL (Artem Sidorenko)
- Fix issue where tag list wasn't refreshed after deleting a tag
- Fix import from gitlab.com (KazSawada)
- Improve implementation to check read access to forks and add pagination
- Don't show any "2FA required" message if it's not actually required
- Fix help keyboard shortcut on relative URL setups (Artem Sidorenko)
- Update Rails to 4.2.5.2
- Fix permissions for deprecated CI build status badge
- Don't show "Welcome to GitLab" when the search didn't return any projects
- Add Todos documentation
v 8.5.1
- Fix group projects styles
......
......@@ -8,6 +8,9 @@
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
- [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute)
- [Implement design & UI elements](#implement-design-ui-elements)
- [Design reference](#design-reference)
- [UI development kit](#ui-development-kit)
- [Issue tracker](#issue-tracker)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
......@@ -83,6 +86,22 @@ GitLab.
This was inspired by [an article by Kent C. Dodds][medium-up-for-grabs].
## Implement design & UI elements
### Design reference
The GitLab design reference can be found in the [gitlab-design] project.
The designs are made using Antetype (`.atype` files). You can use the
[free Antetype viewer (Mac OSX only)] or grab an exported PNG from the design
(the PNG is 1:1).
The current designs can be found in the [`gitlab1.atype` file].
### UI development kit
Implemented UI elements can also be found at https://gitlab.com/help/ui. Please
note that this page isn't comprehensive at this time.
## Issue tracker
To get support for your particular problem please use the
......@@ -299,13 +318,14 @@ to us than having a minimal commit log. The smaller an MR is the more likely it
is it will be merged (quickly). After that you can send more MRs to enhance it.
For examples of feedback on merge requests please look at already
[closed merge requests][closed-merge-requests]. If you would like quick feedback on your merge
request feel free to mention one of the Merge Marshalls of the [core team][core-team].
[closed merge requests][closed-merge-requests]. If you would like quick feedback
on your merge request feel free to mention one of the Merge Marshalls in the
[core team][core-team] or one of the
[Merge request coaches](https://about.gitlab.com/team/).
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
[thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review)
into account.
[Thoughtbot code review guide] into account.
### Merge request description format
......@@ -473,3 +493,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
[`gitlab1.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/gitlab1.atype/
[Thoughtbot code review guide]: https://github.com/thoughtbot/guides/tree/master/code-review
......@@ -6,9 +6,9 @@ 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
gem 'sprockets', '~> 2.12.3'
# Specify a sprockets version due to increased performance
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/6069
gem 'sprockets', '~> 3.3.5'
# Default values for AR models
gem "default_value_for", "~> 3.0.0"
......
......@@ -431,7 +431,6 @@ GEM
railties (>= 4.0.1)
hashie (3.4.3)
highline (1.7.8)
hike (1.2.3)
hipchat (1.5.2)
httparty
mimemagic
......@@ -795,11 +794,8 @@ GEM
spring (>= 0.9.1)
spring-commands-teaspoon (0.0.2)
spring (>= 0.9.1)
sprockets (2.12.4)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets (3.3.5)
rack (> 1, < 3)
sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
......@@ -831,7 +827,7 @@ GEM
rack (~> 1.0)
thor (0.19.1)
thread_safe (0.3.5)
tilt (1.4.1)
tilt (2.0.2)
timfel-krb5-auth (0.8.3)
tinder (1.10.1)
eventmachine (~> 1.0)
......@@ -1057,7 +1053,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.0.0)
spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 2.12.3)
sprockets (~> 3.3.5)
state_machines-activerecord (~> 0.3.0)
task_list (~> 1.0.2)
teaspoon (~> 1.0.0)
......
This diff is collapsed.
......@@ -4,4 +4,7 @@
require File.expand_path('../config/application', __FILE__)
relative_url_conf = File.expand_path('../config/initializers/relative_url', __FILE__)
require relative_url_conf if File.exist?("#{relative_url_conf}.rb")
Gitlab::Application.load_tasks
# Quick Submit behavior
#
# When an input field with the `js-quick-submit` class receives a "Meta+Enter"
# (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, its parent form is
# submitted.
# When a child field of a form with a `js-quick-submit` class receives a
# "Meta+Enter" (Mac) or "Ctrl+Enter" (Linux/Windows) key combination, the form
# is submitted.
#
#= require extensions/jquery
#
# ### Example Markup
#
# <form action="/foo">
# <input type="text" class="js-quick-submit" />
# <textarea class="js-quick-submit"></textarea>
# <form action="/foo" class="js-quick-submit">
# <input type="text" />
# <textarea></textarea>
# <input type="submit" value="Submit" />
# </form>
#
isMac = ->
navigator.userAgent.match(/Macintosh/)
keyCodeIs = (e, keyCode) ->
return false if (e.originalEvent && e.originalEvent.repeat) || e.repeat
return e.keyCode == keyCode
$(document).on 'keydown.quick_submit', '.js-quick-submit', (e) ->
return if (e.originalEvent && e.originalEvent.repeat) || e.repeat
return unless e.keyCode == 13 # Enter
return unless keyCodeIs(e, 13) # Enter
if navigator.userAgent.match(/Macintosh/)
if isMac()
return unless (e.metaKey && !e.altKey && !e.ctrlKey && !e.shiftKey)
else
return unless (e.ctrlKey && !e.altKey && !e.metaKey && !e.shiftKey)
......@@ -27,3 +34,22 @@ $(document).on 'keydown.quick_submit', '.js-quick-submit', (e) ->
$form = $(e.target).closest('form')
$form.find('input[type=submit], button[type=submit]').disable()
$form.submit()
# If the user tabs to a submit button on a `js-quick-submit` form, display a
# tooltip to let them know they could've used the hotkey
$(document).on 'keyup.quick_submit', '.js-quick-submit input[type=submit], .js-quick-submit button[type=submit]', (e) ->
return unless keyCodeIs(e, 9) # Tab
if isMac()
title = "You can also press &#8984;-Enter"
else
title = "You can also press Ctrl-Enter"
$this = $(@)
$this.tooltip(
container: 'body'
html: 'true'
placement: 'auto top'
title: title
trigger: 'manual'
).tooltip('show').one('blur', -> $this.tooltip('hide'))
@Dashboard =
init: ->
$(".projects-list-filter").off('keyup')
this.initSearch()
initSearch: ->
@timer = null
$(".projects-list-filter").on('keyup', ->
clearTimeout(@timer)
@timer = setTimeout(Dashboard.filterResults, 500)
)
filterResults: =>
$('.projects-list-holder').fadeTo(250, 0.5)
form = null
form = $("form#project-filter-form")
search = $(".projects-list-filter").val()
project_filter_url = form.attr('action') + '?' + form.serialize()
$.ajax
type: "GET"
url: form.attr('action')
data: form.serialize()
complete: ->
$('.projects-list-holder').fadeTo(250, 1)
success: (data) ->
$('.projects-list-holder').replaceWith(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: project_filter_url}, document.title, project_filter_url
dataType: "json"
......@@ -16,8 +16,6 @@ class Dispatcher
shortcut_handler = null
switch page
when 'explore:projects:index', 'explore:projects:starred', 'explore:projects:trending'
Dashboard.init()
when 'projects:issues:index'
Issues.init()
shortcut_handler = new ShortcutsNavigation()
......@@ -59,8 +57,6 @@ class Dispatcher
when 'projects:merge_requests:index'
shortcut_handler = new ShortcutsNavigation()
MergeRequests.init()
when 'dashboard:show', 'root:show'
Dashboard.init()
when 'dashboard:activity'
new Activities()
when 'dashboard:projects:starred'
......@@ -107,9 +103,6 @@ class Dispatcher
new ProjectFork()
when 'projects:artifacts:browse'
new BuildArtifacts()
when 'users:show'
new User()
new Activities()
when 'projects:group_links:index'
new GroupsSelect()
when 'projects:mirrors:show', 'projects:mirrors:update'
......
@Pager =
init: (@limit = 0, preload, @disable = false) ->
@loading = $(".loading")
@loading = $('.loading').first()
if preload
@offset = 0
@getOld()
......
......@@ -48,7 +48,7 @@ class @Profile
$filename.text($filename.data('label'))
$('.js-upload-user-avatar').on 'click', ->
$('.edit_user').submit()
$('.edit-user').submit()
$avatarInput.on "change", ->
form = $(this).closest("form")
......@@ -62,4 +62,3 @@ class @Profile
$modalCropImg.attr('src', event.target.result)
fileData = reader.readAsDataURL(this.files[0])
class @ProjectsList
constructor: ->
$(".projects-list .js-expand").on 'click', (e) ->
e.preventDefault()
list = $(this).closest('.projects-list')
@ProjectsList =
init: ->
$(".projects-list-filter").off('keyup')
this.initSearch()
$("#filter_projects").on 'keyup', ->
ProjectsList.filter_results($("#filter_projects"))
initSearch: ->
@timer = null
$(".projects-list-filter").on('keyup', ->
clearTimeout(@timer)
@timer = setTimeout(ProjectsList.filterResults, 500)
)
@filter_results: ($element) ->
terms = $element.val()
filterSelector = $element.data('filter-selector') || 'span.filter-title'
filterResults: =>
$('.projects-list-holder').fadeTo(250, 0.5)
if not terms
$(".projects-list li").show()
$('.gl-pagination').show()
else
$(".projects-list li").each (index) ->
$this = $(this)
name = $this.find(filterSelector).text()
form = null
form = $("form#project-filter-form")
search = $(".projects-list-filter").val()
project_filter_url = form.attr('action') + '?' + form.serialize()
if name.toLowerCase().indexOf(terms.toLowerCase()) == -1
$this.hide()
else
$this.show()
$('.gl-pagination').hide()
$.ajax
type: "GET"
url: form.attr('action')
data: form.serialize()
complete: ->
$('.projects-list-holder').fadeTo(250, 1)
success: (data) ->
$('.projects-list-holder').replaceWith(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: project_filter_url}, document.title, project_filter_url
dataType: "json"
......@@ -13,8 +13,10 @@ class @Shortcuts
if $('#modal-shortcuts').length > 0
$('#modal-shortcuts').modal('show')
else
url = '/help/shortcuts'
url = gon.relative_url_root + url if gon.relative_url_root?
$.ajax(
url: '/help/shortcuts',
url: url,
dataType: 'script',
success: (e) ->
if location and location.length > 0
......
class @User
constructor: ->
constructor: (@opts) ->
$('.profile-groups-avatars').tooltip("placement": "top")
new ProjectsList()
@initTabs()
$('.hide-project-limit-message').on 'click', (e) ->
path = '/'
$.cookie('hide_project_limit_message', 'false', { path: path })
$(@).parents('.project-limit-message').remove()
e.preventDefault()
initTabs: ->
new UserTabs(
parentEl: '.user-profile'
action: @opts.action
)
# UserTabs
#
# Handles persisting and restoring the current tab selection and lazily-loading
# content on the Users#show page.
#
# ### Example Markup
#
# <ul class="nav-links">
# <li class="activity-tab active">
# <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
# Activity
# </a>
# </li>
# <li class="groups-tab">
# <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
# Groups
# </a>
# </li>
# <li class="contributed-tab">
# <a data-action="contributed" data-target="#contributed" data-toggle="tab" href="/u/username/contributed">
# Contributed projects
# </a>
# </li>
# <li class="projects-tab">
# <a data-action="projects" data-target="#projects" data-toggle="tab" href="/u/username/projects">
# Personal projects
# </a>
# </li>
# </ul>
#
# <div class="tab-content">
# <div class="tab-pane" id="activity">
# Activity Content
# </div>
# <div class="tab-pane" id="groups">
# Groups Content
# </div>
# <div class="tab-pane" id="contributed">
# Contributed projects content
# </div>
# <div class="tab-pane" id="projects">
# Projects content
# </div>
# </div>
#
# <div class="loading-status">
# <div class="loading">
# Loading Animation
# </div>
# </div>
#
class @UserTabs
constructor: (opts) ->
{
@action = 'activity'
@defaultAction = 'activity'
@parentEl = $(document)
} = opts
# Make jQuery object if selector is provided
@parentEl = $(@parentEl) if typeof @parentEl is 'string'
# Store the `location` object, allowing for easier stubbing in tests
@_location = location
# Set tab states
@loaded = {}
for item in @parentEl.find('.nav-links a')
@loaded[$(item).attr 'data-action'] = false
# Actions
@actions = Object.keys @loaded
@bindEvents()
# Set active tab
@action = @defaultAction if @action is 'show'
@activateTab(@action)
bindEvents: ->
# Toggle event listeners
@parentEl
.off 'shown.bs.tab', '.nav-links a[data-toggle="tab"]'
.on 'shown.bs.tab', '.nav-links a[data-toggle="tab"]', @tabShown
tabShown: (event) =>
$target = $(event.target)
action = $target.data('action')
source = $target.attr('href')
@setTab(source, action)
@setCurrentAction(action)
activateTab: (action) ->
@parentEl.find(".nav-links .#{action}-tab a").tab('show')
setTab: (source, action) ->
return if @loaded[action] is true
if action is 'activity'
@loadActivities(source)
if action in ['groups', 'contributed', 'projects']
@loadTab(source, action)
loadTab: (source, action) ->
$.ajax
beforeSend: => @toggleLoading(true)
complete: => @toggleLoading(false)
dataType: 'json'
type: 'GET'
url: "#{source}.json"
success: (data) =>
tabSelector = 'div#' + action
@parentEl.find(tabSelector).html(data.html)
@loaded[action] = true
loadActivities: (source) ->
return if @loaded['activity'] is true
$calendarWrap = @parentEl.find('.user-calendar')
$calendarWrap.load($calendarWrap.data('href'))
new Activities()
@loaded['activity'] = true
toggleLoading: (status) ->
@parentEl.find('.loading-status .loading').toggle(status)
setCurrentAction: (action) ->
# Remove possible actions from URL
regExp = new RegExp('\/(' + @actions.join('|') + ')(\.html)?\/?$')
new_state = @_location.pathname
new_state = new_state.replace(/\/+$/, "") # remove trailing slashes
new_state = new_state.replace(regExp, '')
# Append the new action if we're on a tab other than 'activity'
unless action == @defaultAction
new_state += "/#{action}"
# Ensure parameters and hash come along for the ride
new_state += @_location.search + @_location.hash
history.replaceState {turbolinks: true, url: new_state}, document.title, new_state
new_state
......@@ -6,11 +6,15 @@
.cdark { color: #444 }
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.prepend-top-5 { margin-top: 5px; }
.prepend-top-10 { margin-top:10px }
.prepend-top-default { margin-top: $gl-padding !important; }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-default { margin-left:$gl-padding }
.prepend-left-20 { margin-left:20px }
.append-right-5 { margin-right: 5px }
.append-right-10 { margin-right:10px }
.append-right-20 { margin-right:20px }
.append-bottom-10 { margin-bottom:10px }
......@@ -314,7 +318,7 @@ table {
}
.btn-sign-in {
margin-top: 8px;
margin-top: 10px;
text-shadow: none;
}
......
......@@ -69,6 +69,10 @@ label {
&.inline-label {
margin: 0;
}
&.label-light {
font-weight: 600;
}
}
.inline-input-group {
......
......@@ -79,6 +79,10 @@
> .dropdown {
margin-right: $gl-padding-top;
display: inline-block;
&:last-child {
margin-right: 0;
}
}
> .btn {
......
......@@ -13,7 +13,7 @@
transition-duration: .3s;
}
.home {
.gitlab-text-container-link {
z-index: 1;
position: absolute;
left: 0px;
......
......@@ -167,12 +167,6 @@
}
}
.alert-help {
background-color: $background-color;
border: 1px solid $border-color;
color: $gl-gray;
}
// Typography =================================================================
.text-primary,
......
......@@ -196,7 +196,7 @@ body {
h1, h2, h3, h4, h5, h6 {
color: $gl-header-color;
font-weight: 500;
font-weight: 600;
}
/** CODE **/
......
......@@ -34,6 +34,7 @@ $error-exclamation-point: #E62958;
$border-radius-default: 3px;
$list-title-color: #333333;
$list-text-color: #555555;
$profile-settings-link-color: $md-link-color;
/*
* Color schema
......
......@@ -8,6 +8,10 @@
max-width: none;
}
.flash-container {
margin-bottom: $gl-padding;
}
.brand-holder {
font-size: 18px;
line-height: 1.5;
......
......@@ -39,7 +39,7 @@ li.milestone {
margin-right: 10px;
}
.time-elapsed {
.remaining-days {
color: $orange-light;
}
}
......
.global-notifications-form .level-title {
font-size: 15px;
color: #333;
font-weight: bold;
.notification-list-item {
line-height: 34px;
}
.notification-icon-holder {
width: 20px;
float: left;
.notification {
position: relative;
top: 1px;
> .fa {
font-size: 18px;
}
}
.ns-part {
color: $gl-primary;
color: $gl-text-green;
}
.ns-watch {
......
......@@ -5,12 +5,25 @@
}
}
.profile-avatar-form-option {
hr {
margin: 10px 0;
.profile-settings-sidebar {
a {
color: $profile-settings-link-color;
}
}
.avatar-image {
@media (min-width: $screen-sm-min) {
float: left;
margin-bottom: 0;
}
}
.avatar-file-name {
position: relative;
top: 2px;
display: inline-block;
}
.oauth-buttons {
.btn-group {
margin-right: 10px;
......@@ -79,6 +92,13 @@
margin: auto;
}
.user-avatar-button {
.file-name {
display: inline-block;
padding-left: 10px;
}
}
.modal-profile-crop {
.modal-dialog {
width: 500px;
......
.search-results {
.search-result-row {
border-bottom: 1px solid #DDD;
padding-bottom: 15px;
margin-bottom: 15px;
border-bottom: 1px solid $border-color;
padding-bottom: $gl-padding;
margin-bottom: $gl-padding;
&:last-child {
border-bottom: none;
}
}
}
......
......@@ -8,6 +8,7 @@
.badge.todos-pending-count {
background-color: #7f8fa4;
margin-top: -5px;
font-weight: normal;
}
}
}
......
......@@ -3,6 +3,7 @@ module Ci
before_action :project
before_action :authorize_read_project!, except: [:badge]
before_action :no_cache, only: [:badge]
skip_before_action :authenticate_user!, only: [:badge]
protect_from_forgery
def show
......@@ -18,6 +19,7 @@ module Ci
#
def badge
return render_404 unless @project
image = Ci::ImageForBuildService.new.execute(@project, params)
send_file image.path, filename: image.name, disposition: 'inline', type:"image/svg+xml"
end
......
......@@ -2,7 +2,7 @@ module IssuesAction
extend ActiveSupport::Concern
def issues
@issues = get_issues_collection
@issues = get_issues_collection.non_archived
@issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE)
@issues = @issues.preload(:author, :project)
......
......@@ -2,7 +2,7 @@ module MergeRequestsAction
extend ActiveSupport::Concern
def merge_requests
@merge_requests = get_merge_requests_collection
@merge_requests = get_merge_requests_collection.non_archived
@merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE)
@merge_requests = @merge_requests.preload(:author, :target_project)
......
......@@ -6,7 +6,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace)
terms = params['filter_projects']
terms = params[:filter_projects]
if terms.present?
@projects = @projects.search(terms)
......@@ -35,7 +35,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort])
terms = params['filter_projects']
terms = params[:filter_projects]
if terms.present?
@projects = @projects.search(terms)
......
......@@ -6,20 +6,24 @@ class Projects::ForksController < Projects::ApplicationController
def index
base_query = project.forks.includes(:creator)
@forks = if current_user
base_query.where('projects.visibility_level IN (?) OR projects.id IN (?)',
Project.public_and_internal_levels,
current_user.authorized_projects.pluck(:id))
else
base_query.where('projects.visibility_level = ?', Project::PUBLIC)
end
@forks = base_query.merge(ProjectsFinder.new.execute(current_user))
@total_forks_count = base_query.size
@private_forks_count = @total_forks_count - @forks.size
@public_forks_count = @total_forks_count - @private_forks_count
@sort = params[:sort] || 'id_desc'
@forks = @forks.search(params[:filter_projects]) if params[:filter_projects].present?
@forks = @forks.order_by(@sort).page(params[:page]).per(PER_PAGE)
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("projects/forks/_projects", projects: @forks)
}
end
end
end
def new
......
......@@ -34,6 +34,11 @@ class Projects::TagsController < Projects::ApplicationController
def destroy
DeleteTagService.new(project, current_user).execute(params[:id])
respond_to do |format|
format.html do
redirect_to namespace_project_tags_path(@project.namespace, @project)
end
format.js
end
end
end
class SearchController < ApplicationController
skip_before_action :authenticate_user!, :reject_blocked
include SearchHelper
layout 'search'
......
......@@ -3,13 +3,6 @@ class UsersController < ApplicationController
before_action :set_user
def show
@contributed_projects = contributed_projects.joined(@user).reject(&:forked?)
@projects = PersonalProjectsFinder.new(@user).execute(current_user)
@projects = @projects.page(params[:page]).per(PER_PAGE)
@groups = @user.groups.order_id_desc
respond_to do |format|
format.html
......@@ -25,6 +18,45 @@ class UsersController < ApplicationController
end
end
def groups
load_groups
respond_to do |format|
format.html { render 'show' }
format.json do
render json: {
html: view_to_html_string("shared/groups/_list", groups: @groups)
}
end
end
end
def projects
load_projects
respond_to do |format|
format.html { render 'show' }
format.json do
render json: {
html: view_to_html_string("shared/projects/_list", projects: @projects, remote: true)
}
end
end
end
def contributed
load_contributed_projects
respond_to do |format|
format.html { render 'show' }
format.json do
render json: {
html: view_to_html_string("shared/projects/_list", projects: @contributed_projects)
}
end
end
end
def calendar
calendar = contributions_calendar
@timestamps = calendar.timestamps
......@@ -69,6 +101,20 @@ class UsersController < ApplicationController
limit_recent(20, params[:offset])
end
def load_projects
@projects =
PersonalProjectsFinder.new(@user).execute(current_user)
.page(params[:page]).per(PER_PAGE)
end
def load_contributed_projects
@contributed_projects = contributed_projects.joined(@user)
end
def load_groups
@groups = @user.groups.order_id_desc
end
def projects_for_current_user
ProjectsFinder.new.execute(current_user)
end
......
......@@ -10,6 +10,15 @@ module IconsHelper
options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options)
end
def audit_icon(names, options = {})
case names
when "standard"
names = "key"
end
options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options)
end
def spinner(text = nil, visible = false)
css_class = 'loading'
css_class << ' hide' unless visible
......
......@@ -36,4 +36,14 @@ module MilestonesHelper
options_from_collection_for_select(grouped_milestones, 'name', 'title', params[:milestone_title])
end
def milestone_remaining_days(milestone)
if milestone.expired?
content_tag(:strong, 'expired')
elsif milestone.due_date
days = milestone.remaining_days
content = content_tag(:strong, days)
content << " #{'day'.pluralize(days)} remaining"
end
end
end
......@@ -38,6 +38,7 @@ module Issuable
scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.merge(Project.non_archived) }
delegate :name,
:email,
......
......@@ -27,6 +27,7 @@ class Label < ActiveRecord::Base
belongs_to :project
has_many :label_links, dependent: :destroy
has_many :issues, through: :label_links, source: :target, source_type: 'Issue'
has_many :merge_requests, through: :label_links, source: :target, source_type: 'MergeRequest'
validates :color, color: true, allow_blank: false
validates :project, presence: true, unless: Proc.new { |service| service.template? }
......@@ -90,6 +91,10 @@ class Label < ActiveRecord::Base
issues.closed.count
end
def open_merge_requests_count
merge_requests.opened.count
end
def template?
template
end
......
......@@ -111,17 +111,10 @@ class Milestone < ActiveRecord::Base
0
end
# Returns the elapsed time (in percent) since the Milestone creation date until today.
# If the Milestone doesn't have a due_date then returns 0 since we can't calculate the elapsed time.
# If the Milestone is overdue then it returns 100%.
def percent_time_used
return 0 unless due_date
return 100 if expired?
def remaining_days
return 0 if !due_date || expired?
duration = ((created_at - due_date.to_datetime) / 1.day)
days_elapsed = ((created_at - Time.now) / 1.day)
((days_elapsed.to_f / duration) * 100).floor
(due_date - Date.today).to_i
end
def expires_at
......
......@@ -314,7 +314,7 @@ class Project < ActiveRecord::Base
end
def search_by_title(query)
where('projects.archived = ?', false).where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
non_archived.where('LOWER(projects.name) LIKE :query', query: "%#{query.downcase}%")
end
def find_with_namespace(id)
......@@ -817,6 +817,8 @@ class Project < ActiveRecord::Base
old_path_with_namespace = File.join(namespace_dir, path_was)
new_path_with_namespace = File.join(namespace_dir, path)
expire_caches_before_rename(old_path_with_namespace)
if gitlab_shell.mv_repository(old_path_with_namespace, new_path_with_namespace)
# If repository moved successfully we need to send update instructions to users.
# However we cannot allow rollback since we moved repository
......@@ -846,6 +848,22 @@ class Project < ActiveRecord::Base
Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.path)
end
# Expires various caches before a project is renamed.
def expire_caches_before_rename(old_path)
repo = Repository.new(old_path, self)
wiki = Repository.new("#{old_path}.wiki", self)
if repo.exists?
repo.expire_cache
repo.expire_emptiness_caches
end
if wiki.exists?
wiki.expire_cache
wiki.expire_emptiness_caches
end
end
def hook_attrs
{
name: name,
......
......@@ -690,30 +690,38 @@ class Repository
end
end
def revert(user, commit, base_branch, target_branch = nil)
def revert(user, commit, base_branch, revert_tree_id = nil)
source_sha = find_branch(base_branch).target
target_branch ||= base_branch
args = [commit.id, source_sha]
args << { mainline: 1 } if commit.merge_commit?
revert_index = rugged.revert_commit(*args)
return false if revert_index.conflicts?
revert_tree_id ||= check_revert_content(commit, base_branch)
tree_id = revert_index.write_tree(rugged)
return false unless diff_exists?(source_sha, tree_id)
return false unless revert_tree_id
commit_with_hooks(user, target_branch) do |ref|
commit_with_hooks(user, base_branch) do |ref|
committer = user_to_committer(user)
source_sha = Rugged::Commit.create(rugged,
message: commit.revert_message,
author: committer,
committer: committer,
tree: tree_id,
tree: revert_tree_id,
parents: [rugged.lookup(source_sha)],
update_ref: ref)
end
end
def check_revert_content(commit, base_branch)
source_sha = find_branch(base_branch).target
args = [commit.id, source_sha]
args << { mainline: 1 } if commit.merge_commit?
revert_index = rugged.revert_commit(*args)
return false if revert_index.conflicts?
tree_id = revert_index.write_tree(rugged)
return false unless diff_exists?(source_sha, tree_id)
tree_id
end
def diff_exists?(sha1, sha2)
rugged.diff(sha1, sha2).size > 0
end
......
......@@ -171,7 +171,7 @@ class User < ActiveRecord::Base
validates :avatar_crop_x, :avatar_crop_y, :avatar_crop_size,
numericality: { only_integer: true },
presence: true,
if: ->(user) { user.avatar? }
if: ->(user) { user.avatar? && user.avatar_changed? }
before_validation :generate_password, on: :create
before_validation :restricted_signup_domains, on: :create
......@@ -402,7 +402,8 @@ class User < ActiveRecord::Base
def namespace_uniq
# Return early if username already failed the first uniqueness validation
return if self.errors[:username].include?('has already been taken')
return if self.errors.key?(:username) &&
self.errors[:username].include?('has already been taken')
namespace_name = self.username
existing_namespace = Namespace.by_path(namespace_name)
......
......@@ -17,28 +17,28 @@ module Commits
def commit
revert_into = @create_merge_request ? @commit.revert_branch_name : @target_branch
revert_tree_id = repository.check_revert_content(@commit, @target_branch)
if @create_merge_request
# Temporary branch exists and contains the revert commit
return success if repository.find_branch(revert_into)
create_target_branch
end
if revert_tree_id
create_target_branch(revert_into) if @create_merge_request
unless repository.revert(current_user, @commit, revert_into)
repository.revert(current_user, @commit, revert_into, revert_tree_id)
success
else
error_msg = "Sorry, we cannot revert this #{params[:revert_type_title]} automatically.
It may have already been reverted, or a more recent commit may have updated some of its content."
raise ReversionError, error_msg
end
success
end
private
def create_target_branch
def create_target_branch(new_branch)
# Temporary branch exists and contains the revert commit
return success if repository.find_branch(new_branch)
result = CreateBranchService.new(@project, current_user)
.execute(@commit.revert_branch_name, @target_branch, source_project: @source_project)
.execute(new_branch, @target_branch, source_project: @source_project)
if result[:status] == :error
raise ReversionError, "There was an error creating the source branch: #{result[:message]}"
......
......@@ -2,7 +2,7 @@
%h3.page-title Report abuse
%p Please use this form to report users who create spam issues, comments or behave inappropriately.
%hr
= form_for @abuse_report, html: { class: 'form-horizontal js-requires-input'} do |f|
= form_for @abuse_report, html: { class: 'form-horizontal js-quick-submit js-requires-input'} do |f|
= f.hidden_field :user_id
- if @abuse_report.errors.any?
.alert.alert-danger
......@@ -16,7 +16,7 @@
.form-group
= f.label :message, class: 'control-label'
.col-sm-10
= f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true, value: sanitize(@ref_url)
= f.text_area :message, class: "form-control", rows: 2, required: true, value: sanitize(@ref_url)
.help-block
Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment.
......
......@@ -3,7 +3,7 @@
.js-broadcast-message-preview
= render_broadcast_message(@broadcast_message.message.presence || "Your message here")
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-requires-input'} do |f|
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-quick-submit js-requires-input'} do |f|
-if @broadcast_message.errors.any?
.alert.alert-danger
- @broadcast_message.errors.full_messages.each do |msg|
......@@ -11,7 +11,7 @@
.form-group
= f.label :message, class: 'control-label'
.col-sm-10
= f.text_area :message, class: "form-control js-quick-submit js-autosize",
= f.text_area :message, class: "form-control js-autosize",
required: true,
data: { preview_path: preview_admin_broadcast_messages_path }
.form-group.js-toggle-colors-container
......
.projects-list-holder
= render 'shared/projects/list', projects: @projects, ci: true
:javascript
Dashboard.init()
= render 'shared/projects/list', projects: @projects, ci: true
......@@ -10,7 +10,7 @@
- if @last_push
= render "events/event_last_push", event: @last_push
- if @projects.any?
- if @projects.any? || params[:filter_projects]
= render 'projects'
- else
= render "zero_authorized_projects"
.pull-right.hidden-sm.hidden-xs
- if current_user
.dropdown.inline.append-right-10
- if current_user
.dropdown
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-globe
= icon('globe')
%span.light Visibility:
- if params[:visibility_level].present?
= visibility_level_label(params[:visibility_level].to_i)
......@@ -19,10 +18,10 @@
= visibility_level_icon(level)
= visibility_level_label(level)
- if @tags.present?
.dropdown.inline.append-right-10
- if @tags.present?
.dropdown
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-tags
= icon('tags')
%span.light Tags:
- if params[:tag].present?
= params[:tag]
......
- if projects.any?
.projects-list-holder
= render 'shared/projects/list', projects: projects
- else
.nothing-here-block
No such projects
= render 'shared/projects/list', projects: projects
......@@ -9,7 +9,7 @@
.top-area
= render 'explore/projects/nav'
.gray-content-block.second-block.clearfix
.nav-controls
= render 'filter'
= render 'projects', projects: @projects
......@@ -8,5 +8,4 @@
= icon('plus')
New Project
.projects-list-holder
= render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true
= render 'shared/projects/list', projects: @projects, stars: false, skip_namespace: true
- user = member.user
- return unless user || member.invite?
- show_roles = local_assigns.fetch(:show_roles, true)
%li{class: "#{dom_class(member)} js-toggle-container", id: dom_id(member)}
%span{class: ("list-item-name" if show_controls)}
......@@ -28,7 +29,7 @@
= link_to resend_invite_group_group_member_path(@group, member), method: :post, class: "btn-xs btn", title: 'Resend invite' do
Resend invite
- if should_user_see_group_roles?(current_user, @group)
- if show_roles && should_user_see_group_roles?(current_user, @group)
%span.pull-right
%strong.member-access-level= member.human_access
- if show_controls
......
......@@ -8,18 +8,18 @@
This will create milestone in every selected project
%hr
= form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f|
= form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-quick-submit js-requires-input' } do |f|
.row
.col-md-6
.form-group
= f.label :title, "Title", class: "control-label"
.col-sm-10
= f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true, autofocus: true
= f.text_field :title, maxlength: 255, class: "form-control", required: true, autofocus: true
.form-group.milestone-description
= f.label :description, "Description", class: "control-label"
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit'
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.clearfix
.error-alert
.form-group
......
......@@ -4,7 +4,7 @@
.header-logo
%a#logo
= brand_header_logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do
= link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do
.gitlab-text-container
%h3 GitLab
......
......@@ -5,11 +5,7 @@
-# Ideally this would be inside the head, but turbolinks only evaluates page-specific JS in the body.
= yield :scripts_body_top
- if current_user
= render "layouts/header/default", title: header_title
- else
= render "layouts/header/public", title: header_title
= render 'layouts/page', sidebar: sidebar
= yield :scripts_body
......@@ -4,7 +4,7 @@
.header-logo
%a#logo
= brand_header_logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do
= link_to root_path, class: 'gitlab-text-container-link', title: 'Dashboard', id: 'js-shortcuts-home' do
.gitlab-text-container
%h3 GitLab
......
......@@ -13,6 +13,7 @@
%li.visible-sm.visible-xs
= link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('search')
- if current_user
- if session[:impersonator_id]
%li.impersonation
= link_to stop_impersonation_admin_users_path, method: :delete, title: 'Stop Impersonation', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
......@@ -37,6 +38,10 @@
%li
= link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('sign-out')
- else
.pull-right
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
%h1.title= title
......
%header.navbar.navbar-fixed-top.navbar-gitlab{ class: nav_header_class }
%div{ class: fluid_layout ? "container-fluid" : "container-fluid" }
.header-content
- unless current_controller?('sessions')
.pull-right
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
%h1.title= title
= render 'shared/outdated_browser'
.table-holder
%table.table#audits
%thead
%tr
%th Action
%th When
%h5.prepend-top-0
History of authentications
%tbody
%ul.well-list
- events.each do |event|
%tr
%td
%span
%li
%span.description
= audit_icon(event.details[:with], class: "append-right-5")
Signed in with
%b= event.details[:with]
= event.details[:with]
authentication
%td #{time_ago_in_words event.created_at} ago
%span.pull-right
#{time_ago_in_words event.created_at} ago
= paginate events, theme: "gitlab"
- page_title "Audit Log"
- header_title page_title, audit_log_profile_path
.alert.alert-help.prepend-top-default
History of authentications
.prepend-top-default
= render 'event_table', events: @events
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
%h3.prepend-top-0
= page_title
%p
This is a security log of important events involving your account.
.col-lg-9
= render 'event_table', events: @events
%li
%span.notification.fa.fa-holder
%li.notification-list-item
%span.notification.fa.fa-holder.append-right-5
- if notification.global?
= notification_icon(@notification)
- else
......
- page_title "Notifications"
- header_title page_title, profile_notifications_path
.prepend-top-default
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications form-horizontal global-notifications-form' } do |f|
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f|
-if @user.errors.any?
%div.alert.alert-danger
%ul
......@@ -10,15 +9,22 @@
%li= msg
= hidden_field_tag :notification_type, 'global'
.row
.col-lg-3.profile-settings-sidebar
%h4
= page_title
%p
You can specify notification level per group or per project.
%p
By default, all projects and groups will use the global notifications setting.
.col-lg-9
%h5
Global notification settings
.form-group
= f.label :notification_email, class: "control-label"
.col-sm-10
= f.select :notification_email, @user.all_emails, { include_blank: false }, class: "form-control"
= f.label :notification_email, class: "label-light"
= f.select :notification_email, @user.all_emails, { include_blank: false }, class: "select2"
.form-group
= f.label :notification_level, class: 'control-label'
.col-sm-10
= f.label :notification_level, class: 'label-light'
.radio
= f.label :notification_level, value: Notification::N_DISABLED do
= f.radio_button :notification_level, Notification::N_DISABLED
......@@ -47,27 +53,21 @@
Watch
%p You will receive notifications for any activity
.gray-content-block
= f.submit 'Save changes', class: "btn btn-create"
.row.all-notifications.prepend-top-default
.col-md-6
%p
You can also specify notification level per group or per project.
%br
By default, all projects and groups will use the notification level set above.
%h4 Groups:
.prepend-top-default
= f.submit 'Update settings', class: "btn btn-create"
%hr
%h5
Groups (#{@group_members.count})
%div
%ul.bordered-list
- @group_members.each do |group_member|
- notification = Notification.new(group_member)
= render 'settings', type: 'group', membership: group_member, notification: notification
.col-md-6
%p
To specify the notification level per project of a group you belong to,
%br
you need to be a member of the project itself, not only its group.
%h4 Projects:
%h5
Projects (#{@project_members.count})
%p.account-well
To specify the notification level per project of a group you belong to, you need to be a member of the project itself, not only its group.
.append-bottom-default
%ul.bordered-list
- @project_members.each do |project_member|
- notification = Notification.new(project_member)
......
- page_title 'Preferences'
- header_title page_title, profile_preferences_path
.alert.alert-help.prepend-top-default
These settings allow you to customize the appearance and behavior of the site.
They are saved with your account and will persist to any device you use to
access the site.
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'js-preferences-form form-horizontal'} do |f|
.panel.panel-default.application-theme
.panel-heading
= form_for @user, url: profile_preferences_path, remote: true, method: :put, html: {class: 'row prepend-top-default js-preferences-form'} do |f|
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Application theme
.panel-body
%p
This setting allows you to customize the appearance of the site, ex. sidebar.
.col-lg-9.application-theme
- Gitlab::Themes.each do |theme|
= label_tag do
.preview{class: theme.css_class}
= f.radio_button :theme_id, theme.id
= theme.name
.panel.panel-default.syntax-theme
.panel-heading
.col-sm-12
%hr
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Syntax highlighting theme
.panel-body
%p
This setting allow you to customize the appearance of the syntax.
.col-lg-9.syntax-theme
- Gitlab::ColorSchemes.each do |scheme|
= label_tag do
.preview= image_tag "#{scheme.css_class}-scheme-preview.png"
= f.radio_button :color_scheme_id, scheme.id
= scheme.name
.panel.panel-default
.panel-heading
.col-sm-12
%hr
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Behavior
.panel-body
%p
This setting allows you to customize the behavior of the system layout and default views.
.col-lg-9
.form-group
= f.label :layout, class: 'control-label' do
= f.label :layout, class: 'label-light' do
Layout width
.col-sm-10
= f.select :layout, layout_choices, {}, class: 'form-control'
.help-block
Choose between fixed (max. 1200px) and fluid (100%) application layout.
.form-group
= f.label :dashboard, class: 'control-label' do
= f.label :dashboard, class: 'label-light' do
Default Dashboard
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-dashboard', target: '_blank')
.col-sm-10
= f.select :dashboard, dashboard_choices, {}, class: 'form-control'
.form-group
= f.label :project_view, class: 'control-label' do
= f.label :project_view, class: 'label-light' do
Project view
= link_to('(?)', help_page_path('profile', 'preferences') + '#default-project-view', target: '_blank')
.col-sm-10
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.help-block
Choose what content you want to see on a project's home page.
.panel-footer
.form-group
= f.submit 'Save changes', class: 'btn btn-save'
.alert.alert-help.prepend-top-default
This information will appear on your profile.
- if current_user.ldap_user?
Some options are unavailable for LDAP accounts
.prepend-top-default
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit_user form-horizontal" }, authenticity_token: true do |f|
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f|
= f.hidden_field :avatar_crop_x
= f.hidden_field :avatar_crop_y
= f.hidden_field :avatar_crop_size
-if @user.errors.any?
%div.alert.alert-danger
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
.row
.col-md-7
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Public Avatar
%p
- if @user.avatar?
You can change your avatar here
- if Gitlab.config.gravatar.enabled
or remove the current avatar to revert to #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host}
- else
You can upload an avatar here
- if Gitlab.config.gravatar.enabled
or change it at #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host}
.col-lg-9
.clearfix.avatar-image.append-bottom-default
= image_tag avatar_icon(@user, 160), alt: '', class: 'avatar s160'
%h5.prepend-top-0
Upload new avatar
.prepend-top-5.append-bottom-10
%a.btn.js-choose-user-avatar-button
Browse file...
%span.avatar-file-name.prepend-left-default.js-avatar-filename No file chosen
= f.file_field :avatar, class: "js-user-avatar-input hidden"
.help-block
The maximum file size allowed is 200KB.
- if @user.avatar?
%hr
= link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-gray"
%hr
.row
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
Main settings
%p
This information will appear on your profile.
- if current_user.ldap_user?
Some options are unavailable for LDAP accounts
.col-lg-9
.form-group
= f.label :name, class: "control-label"
.col-sm-10
= f.label :name, class: "label-light"
= f.text_field :name, class: "form-control", required: true
%span.help-block Enter your name, so people you know can recognize you.
.form-group
= f.label :email, class: "control-label"
.col-sm-10
= f.label :email, class: "label-light"
- if @user.ldap_user? && @user.ldap_email?
= f.text_field :email, class: "form-control", required: true, readonly: true
%span.help-block.light
......@@ -41,66 +72,30 @@
- else
%span.help-block We also use email for avatar detection if no avatar is uploaded.
.form-group
= f.label :public_email, class: "control-label"
.col-sm-10
= f.label :public_email, class: "label-light"
= f.select :public_email, options_for_select(@user.all_emails, selected: @user.public_email), {include_blank: 'Do not show on profile'}, class: "select2"
%span.help-block This email will be displayed on your public profile.
.form-group
= f.label :skype, class: "control-label"
.col-sm-10= f.text_field :skype, class: "form-control"
= f.label :skype, class: "label-light"
= f.text_field :skype, class: "form-control"
.form-group
= f.label :linkedin, class: "control-label"
.col-sm-10= f.text_field :linkedin, class: "form-control"
= f.label :linkedin, class: "label-light"
= f.text_field :linkedin, class: "form-control"
.form-group
= f.label :twitter, class: "control-label"
.col-sm-10= f.text_field :twitter, class: "form-control"
= f.label :twitter, class: "label-light"
= f.text_field :twitter, class: "form-control"
.form-group
= f.label :website_url, 'Website', class: "control-label"
.col-sm-10= f.text_field :website_url, class: "form-control"
= f.label :website_url, 'Website', class: "label-light"
= f.text_field :website_url, class: "form-control"
.form-group
= f.label :location, 'Location', class: "control-label"
.col-sm-10= f.text_field :location, class: "form-control"
= f.label :location, 'Location', class: "label-light"
= f.text_field :location, class: "form-control"
.form-group
= f.label :bio, class: "control-label"
.col-sm-10
= f.label :bio, class: "label-light"
= f.text_area :bio, rows: 4, class: "form-control", maxlength: 250
%span.help-block Tell us about yourself in fewer than 250 characters.
.col-md-5
.light-well
= image_tag avatar_icon(@user, 160), alt: '', class: 'avatar s160'
.clearfix
.profile-avatar-form-option
%p.light
- if @user.avatar?
You can change your avatar here
- if Gitlab.config.gravatar.enabled
%br
or remove the current avatar to revert to #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host}
- else
You can upload an avatar here
- if Gitlab.config.gravatar.enabled
%br
or change it at #{link_to Gitlab.config.gravatar.host, "http://" + Gitlab.config.gravatar.host}
%hr
%a.choose-btn.btn.btn-sm.js-choose-user-avatar-button
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-user-avatar-input hidden"
= f.hidden_field :avatar_crop_x
= f.hidden_field :avatar_crop_y
= f.hidden_field :avatar_crop_size
.light The maximum file size allowed is 200KB.
- if @user.avatar?
%hr
= link_to 'Remove avatar', profile_avatar_path, data: { confirm: "Avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
.form-actions
= f.submit 'Save changes', class: "btn btn-success"
.prepend-top-default.append-bottom-default
= f.submit 'Update profile settings', class: "btn btn-success"
= link_to "Cancel", user_path(current_user), class: "btn btn-cancel"
.modal.modal-profile-crop
......
......@@ -10,7 +10,7 @@
%span.editor-file-name
\/
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
required: true, class: 'form-control new-file-name js-quick-submit'
required: true, class: 'form-control new-file-name'
.pull-right
= select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'select2'
......
......@@ -5,7 +5,7 @@
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3.page-title Create New Directory
.modal-body
= form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form js-requires-input' do
= form_tag namespace_project_create_dir_path(@project.namespace, @project, @id), method: :post, remote: false, class: 'form-horizontal js-create-dir-form js-quick-submit js-requires-input' do
.form-group
= label_tag :dir_name, 'Directory name', class: 'control-label'
.col-sm-10
......
......@@ -6,7 +6,7 @@
%h3.page-title Delete #{@blob.name}
.modal-body
= form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-replace-blob-form js-requires-input' do
= form_tag namespace_project_blob_path(@project.namespace, @project, @id), method: :delete, class: 'form-horizontal js-replace-blob-form js-quick-submit js-requires-input' do
= render 'shared/new_commit_form', placeholder: "Delete #{@blob.name}"
.form-group
......
......@@ -5,7 +5,7 @@
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3.page-title #{title}
.modal-body
= form_tag form_path, method: method, class: 'js-upload-blob-form form-horizontal' do
= form_tag form_path, method: method, class: 'js-quick-submit js-upload-blob-form form-horizontal' do
.dropzone
.dropzone-previews.blob-upload-dropzone-previews
%p.dz-message.light
......
......@@ -13,7 +13,7 @@
= icon('eye')
= editing_preview_title(@blob.name)
= form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-requires-input js-edit-blob-form') do
= form_tag(namespace_project_update_blob_path(@project.namespace, @project, @id), method: :put, class: 'form-horizontal js-quick-submit js-requires-input js-edit-blob-form') do
= render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
= render 'shared/new_commit_form', placeholder: "Update #{@blob.name}"
......
......@@ -5,7 +5,7 @@
New File
.file-editor
= form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal js-new-blob-form js-requires-input') do
= form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal js-new-blob-form js-quick-submit js-requires-input') do
= render 'projects/blob/editor', ref: @ref
= render 'shared/new_commit_form', placeholder: "Add new file"
......
= render 'shared/projects/list', projects: projects, use_creator_avatar: true,
forks: true, show_last_commit_as_description: true
......@@ -4,6 +4,7 @@
== #{pluralize(@total_forks_count, 'fork')}: #{full_count_title}
.nav-controls
= form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
= search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter project-filter-form-field form-control input-short',
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
......@@ -38,18 +39,10 @@
Fork
.projects-list-holder
- if @forks.blank?
%ul.content-list
%li
.nothing-here-block No forks to show
- else
= render 'shared/projects/list', projects: @forks, use_creator_avatar: true,
forks: true, show_last_commit_as_description: true
= render 'projects', projects: @forks
- if @private_forks_count > 0
%ul.projects-list.private-forks-notice
%li.project-row
- if @private_forks_count > 0
.private-forks-notice
= icon('lock fw', base: 'circle', class: 'fa-lg private-fork-icon')
%strong= pluralize(@private_forks_count, 'private fork')
%span you have no access to.
= form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form js-requires-input' } do |f|
= form_for [@project.namespace.becomes(Namespace), @project, @issue], html: { class: 'form-horizontal issue-form gfm-form js-quick-submit js-requires-input' } do |f|
= render 'shared/issuable/form', f: f, issuable: @issue
:javascript
......
......@@ -29,6 +29,7 @@
%span.creator
&middot;
by #{link_to_member(@project, @issue.author, size: 24)}
= '@' + @issue.author.username
&middot;
= time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
......
= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form js-requires-input' } do |f|
= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f|
-if @label.errors.any?
.row
.col-sm-offset-2.col-sm-10
......@@ -10,7 +10,7 @@
.form-group
= f.label :title, class: 'control-label'
.col-sm-10
= f.text_field :title, class: "form-control js-quick-submit", required: true, autofocus: true
= f.text_field :title, class: "form-control", required: true, autofocus: true
.form-group
= f.label :description, class: 'control-label'
.col-sm-10
......
......@@ -2,6 +2,10 @@
= render "shared/label_row", label: label
.pull-right
%strong.append-right-20
= link_to_label(label, type: :merge_request) do
= pluralize label.open_merge_requests_count, 'open merge request'
%strong.append-right-20
= link_to_label(label) do
= pluralize label.open_issues_count, 'open issue'
......
......@@ -6,6 +6,7 @@
%span.creator
&middot;
by #{link_to_member(@project, @merge_request.author, size: 24)}
= '@' + @merge_request.author.username
&middot;
= time_ago_with_tooltip(@merge_request.created_at)
......
- status_class = @ci_commit ? " ci-#{@ci_commit.status}" : nil
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f|
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
.accept-merge-holder.clearfix.js-toggle-container
.clearfix
......
= form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form js-requires-input'} do |f|
= form_for [@project.namespace.becomes(Namespace), @project, @milestone], html: {class: 'form-horizontal milestone-form gfm-form js-quick-submit js-requires-input'} do |f|
-if @milestone.errors.any?
.alert.alert-danger
%ul
......@@ -9,12 +9,12 @@
.form-group
= f.label :title, "Title", class: "control-label"
.col-sm-10
= f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true, autofocus: true
= f.text_field :title, maxlength: 255, class: "form-control", required: true, autofocus: true
.form-group.milestone-description
= f.label :description, "Description", class: "control-label"
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit'
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
= render 'projects/notes/hints'
.clearfix
.error-alert
......
......@@ -60,9 +60,7 @@
%strong== #{@milestone.percent_complete}%
complete
%span.milestone-stat
%span.time-elapsed
%strong== #{@milestone.percent_time_used}%
time elapsed
%span.remaining-days= milestone_remaining_days(@milestone)
%span.pull-right.tab-issues-buttons
- if can?(current_user, :create_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { milestone_id: @milestone.id }), class: "btn btn-grouped", title: "New Issue" do
......
.note-edit-form
= form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true do |f|
= form_for note, url: namespace_project_note_path(@project.namespace, @project, note), method: :put, remote: true, authenticity_token: true, class: 'js-quick-submit' do |f|
= note_target_fields(note)
= render layout: 'projects/md_preview', locals: { preview_class: 'md-preview' } do
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field js-quick-submit'
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
= render 'projects/notes/hints'
.note-form-actions
......
= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form common-note-form gfm-form" }, authenticity_token: true do |f|
= form_for [@project.namespace.becomes(Namespace), @project, @note], remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new_note js-new-note-form js-quick-submit common-note-form gfm-form" }, authenticity_token: true do |f|
= hidden_field_tag :view, diff_view
= hidden_field_tag :line_type
= note_target_fields(@note)
......@@ -8,7 +8,7 @@
= f.hidden_field :noteable_type
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-quick-submit'
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text'
= render 'projects/notes/hints'
.error-alert
......
......@@ -9,9 +9,9 @@
%strong #{@tag.name}
.prepend-top-default
= form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal gfm-form release-form' }) do |f|
= form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal gfm-form release-form js-quick-submit' }) do |f|
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit form-control'
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
= render 'projects/notes/hints'
.error-alert
.form-actions.prepend-top-default
......
$('.js-totaltags-count').html("#{@repository.tags.size}");
- if @repository.tags.empty?
$('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
......@@ -10,7 +10,7 @@
New Tag
%hr
= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal gfm-form tag-form js-requires-input" do
= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal gfm-form tag-form js-quick-submit js-requires-input" do
.form-group
= label_tag :tag_name, nil, class: 'control-label'
.col-sm-10
......@@ -30,7 +30,7 @@
= label_tag :release_description, 'Release notes', class: 'control-label'
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', attr: :release_description, classes: 'description js-quick-submit form-control'
= render 'projects/zen', attr: :release_description, classes: 'description form-control'
= render 'projects/notes/hints'
.help-block Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page.
.form-actions
......
= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form prepend-top-default' } do |f|
= form_for [@project.namespace.becomes(Namespace), @project, @page], method: @page.persisted? ? :put : :post, html: { class: 'form-horizontal wiki-form gfm-form prepend-top-default js-quick-submit' } do |f|
-if @page.errors.any?
#error_explanation
.alert.alert-danger
......@@ -15,7 +15,7 @@
= f.label :content, class: 'control-label'
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
= render 'projects/zen', f: f, attr: :content, classes: 'description form-control js-quick-submit'
= render 'projects/zen', f: f, attr: :content, classes: 'description form-control'
= render 'projects/notes/hints'
.clearfix
......
......@@ -11,4 +11,4 @@
= button_tag 'Search', class: "btn btn-primary"
- unless params[:snippets].eql? 'true'
%br
= render 'filter'
= render 'filter' if current_user
......@@ -7,7 +7,7 @@
.max-width-marker
= text_area_tag 'commit_message',
(params[:commit_message] || local_assigns[:text]),
class: 'form-control js-commit-message js-quick-submit', placeholder: local_assigns[:placeholder],
class: 'form-control js-commit-message', placeholder: local_assigns[:placeholder],
required: true, rows: (local_assigns[:rows] || 3),
id: "commit_message-#{nonce}"
- if local_assigns[:hint]
......
- if groups.any?
%ul.content-list
- groups.each_with_index do |group, i|
= render "shared/groups/group", group: group
- else
%h3 No groups found
......@@ -9,7 +9,7 @@
= f.label :title, class: 'control-label'
.col-sm-10
= f.text_field :title, maxlength: 255, autofocus: true, autocomplete: 'off',
class: 'form-control pad js-gfm-input js-quick-submit', required: true
class: 'form-control pad js-gfm-input', required: true
- if issuable.is_a?(MergeRequest)
%p.help-block
......@@ -25,7 +25,7 @@
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control js-quick-submit'
classes: 'description form-control'
= render 'projects/notes/hints'
.clearfix
.error-alert
......
......@@ -6,25 +6,19 @@
- ci = false unless local_assigns[:ci] == true
- skip_namespace = false unless local_assigns[:skip_namespace] == true
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
- remote = false unless local_assigns[:remote] == true
%ul.projects-list.content-list
.projects-list-holder
- if projects.any?
%ul.projects-list.content-list
- projects.each_with_index do |project, i|
- css_class = (i >= projects_limit) ? 'hide' : nil
= render "shared/projects/project", project: project, skip_namespace: skip_namespace,
avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar,
forks: forks, show_last_commit_as_description: show_last_commit_as_description
- if projects.size > projects_limit && projects.kind_of?(Array)
%li.bottom.center
.light
#{projects_limit} of #{pluralize(projects.count, 'project')} displayed.
= link_to '#', class: 'js-expand' do
Show all
= paginate projects, theme: "gitlab" if projects.respond_to? :total_pages
= paginate(projects, remote: remote, theme: "gitlab") if projects.respond_to? :total_pages
- else
%h3 No projects found
.nothing-here-block No projects found
:javascript
new ProjectsList();
Dashboard.init();
ProjectsList.init();
......@@ -8,7 +8,8 @@
= render 'shared/show_aside'
.cover-block
.user-profile
.cover-block
.cover-controls
- if @user == current_user
= link_to profile_path, class: 'btn btn-gray' do
......@@ -69,56 +70,48 @@
= icon('map-marker')
= @user.location
%ul.nav-links.center
%li.active
= link_to "#activity", 'data-toggle' => 'tab' do
%ul.nav-links.center.user-profile-nav
%li.activity-tab
= link_to user_calendar_activities_path, data: {target: 'div#activity', action: 'activity', toggle: 'tab'} do
Activity
- if @groups.any?
%li
= link_to "#groups", 'data-toggle' => 'tab' do
%li.groups-tab
= link_to user_groups_path, data: {target: 'div#groups', action: 'groups', toggle: 'tab'} do
Groups
- if @contributed_projects.present?
%li
= link_to "#contributed", 'data-toggle' => 'tab' do
%li.contributed-tab
= link_to user_contributed_projects_path, data: {target: 'div#contributed', action: 'contributed', toggle: 'tab'} do
Contributed projects
- if @projects.present?
%li
= link_to "#personal", 'data-toggle' => 'tab' do
%li.projects-tab
= link_to user_projects_path, data: {target: 'div#projects', action: 'projects', toggle: 'tab'} do
Personal projects
%div{ class: container_class }
%div{ class: container_class }
.tab-content
.tab-pane.active#activity
#activity.tab-pane
.gray-content-block.white.second-block
%div{ class: container_class }
.user-calendar
.user-calendar{data: {href: user_calendar_path}}
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
.content_list
.content_list{ data: {href: user_path} }
= spinner
- if @groups.any?
.tab-pane#groups
%ul.content-list
- @groups.each do |group|
= render 'shared/groups/group', group: group
- if @contributed_projects.present?
.tab-pane#contributed
.contributed-projects
= render 'shared/projects/list',
projects: @contributed_projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: true
- if @projects.present?
.tab-pane#personal
.personal-projects
= render 'shared/projects/list',
projects: @projects.sort_by(&:star_count).reverse,
projects_limit: 10, stars: true, avatar: true
#groups.tab-pane
- # This tab is always loaded via AJAX
#contributed.contributed-projects.tab-pane
- # This tab is always loaded via AJAX
#projects.tab-pane
- # This tab is always loaded via AJAX
.loading-status
= spinner
:javascript
$(".user-calendar").load("#{user_calendar_path}");
var userProfile;
userProfile = new User({
action: "#{controller.action_name}"
});
......@@ -54,14 +54,6 @@ module Gitlab
config.action_view.sanitized_allowed_protocols = %w(smb)
# Relative URL support
# WARNING: We recommend using an FQDN to host GitLab in a root path instead
# of using a relative URL.
# Documentation: http://doc.gitlab.com/ce/install/relative_url.html
# Uncomment and customize the following line to run in a non-root path
#
# config.relative_url_root = "/gitlab"
config.middleware.use Rack::Attack
# Allow access to GitLab API from other domains
......
......@@ -276,10 +276,6 @@ Settings.gitlab_ci['builds_path'] = File.expand_path(Settings.gitlab_c
#
Settings['incoming_email'] ||= Settingslogic.new({})
Settings.incoming_email['enabled'] = false if Settings.incoming_email['enabled'].nil?
Settings.incoming_email['port'] = 143 if Settings.incoming_email['port'].nil?
Settings.incoming_email['ssl'] = false if Settings.incoming_email['ssl'].nil?
Settings.incoming_email['start_tls'] = false if Settings.incoming_email['start_tls'].nil?
Settings.incoming_email['mailbox'] = "inbox" if Settings.incoming_email['mailbox'].nil?
#
# Build Artifacts
......
# Relative URL support
# WARNING: We recommend using an FQDN to host GitLab in a root path instead
# of using a relative URL.
# Documentation: http://doc.gitlab.com/ce/install/relative_url.html
# Copy this file to relative_url.rb and customize it to run in a non-root path
#
Rails.application.configure do
config.relative_url_root = "/gitlab"
end
:mailboxes:
<%
require_relative 'config/environment.rb'
require "yaml"
require "json"
if Gitlab::IncomingEmail.enabled?
config = Gitlab::IncomingEmail.config
rails_env = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
config_file = ENV["MAIL_ROOM_GITLAB_CONFIG_FILE"] || "config/gitlab.yml"
if File.exists?(config_file)
all_config = YAML.load_file(config_file)[rails_env]
config = all_config["incoming_email"] || {}
config['enabled'] = false if config['enabled'].nil?
config['port'] = 143 if config['port'].nil?
config['ssl'] = false if config['ssl'].nil?
config['start_tls'] = false if config['start_tls'].nil?
config['mailbox'] = "inbox" if config['mailbox'].nil?
if config['enabled'] && config['address'] && config['address'].include?('%{key}')
redis_config_file = "config/resque.yml"
redis_url =
if File.exists?(redis_config_file)
YAML.load_file(redis_config_file)[Rails.env]
YAML.load_file(redis_config_file)[rails_env]
else
"redis://localhost:6379"
end
%>
-
:host: <%= config.host.to_json %>
:port: <%= config.port.to_json %>
:ssl: <%= config.ssl.to_json %>
:start_tls: <%= config.start_tls.to_json %>
:email: <%= config.user.to_json %>
:password: <%= config.password.to_json %>
:host: <%= config['host'].to_json %>
:port: <%= config['port'].to_json %>
:ssl: <%= config['ssl'].to_json %>
:start_tls: <%= config['start_tls'].to_json %>
:email: <%= config['user'].to_json %>
:password: <%= config['password'].to_json %>
:name: <%= config.mailbox.to_json %>
:name: <%= config['mailbox'].to_json %>
:delete_after_delivery: true
......@@ -36,4 +48,5 @@ if Gitlab::IncomingEmail.enabled?
:arbitration_options:
:redis_url: <%= redis_url.to_json %>
:namespace: mail_room:gitlab
<% end %>
<% end %>
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