Commit 3a9682a3 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge dev.gitlab.org:gitlab/gitlabhq into upstream-ce

Conflicts:
	VERSION
	app/helpers/selects_helper.rb
	app/models/project.rb
	app/views/devise/sessions/new.html.haml
	app/views/groups/_settings_nav.html.haml
	app/views/layouts/nav/_admin.html.haml
	app/views/profiles/keys/_key.html.haml
	app/views/profiles/keys/index.html.haml
	app/views/profiles/keys/show.html.haml
	app/views/projects/merge_requests/show/_mr_accept.html.haml
	config/routes.rb
	db/schema.rb
	doc/api/projects.md
	features/steps/shared/paths.rb
parents 859628ed d531de0b
*.log
*.swp
.DS_Store
.bundle
.chef
.directory
.envrc
.gitlab_shell_secret
.idea
.rbenv-version
.rbx/
db/*.sqlite3
db/*.sqlite3-journal
log/*.log*
tmp/
.sass-cache/
coverage/*
backups/*
*.swp
public/uploads/
.ruby-version
.ruby-gemset
.ruby-version
.rvmrc
.rbenv-version
.directory
nohup.out
Vagrantfile
.sass-cache/
.secret
.vagrant
config/gitlab.yml
Vagrantfile
backups/*
config/aws.yml
config/database.yml
config/gitlab.yml
config/initializers/omniauth.rb
config/initializers/rack_attack.rb
config/initializers/smtp_settings.rb
config/unicorn.rb
config/resque.yml
config/aws.yml
config/unicorn.rb
coverage/*
db/*.sqlite3
db/*.sqlite3-journal
db/data.yml
.idea
.DS_Store
.chef
vendor/bundle/*
rails_best_practices_output.html
doc/code/*
.secret
*.log
public/uploads.*
public/assets/
.envrc
dump.rdb
log/*.log*
nohup.out
public/assets/
public/uploads.*
public/uploads/
rails_best_practices_output.html
tags
.gitlab_shell_secret
tmp/
vendor/bundle/*
v 7.7.0
-
-
- Add Jetbrains Teamcity CI service (Jason Lippert)
-
-
- Mention notification level
- Markdown preview in wiki (Yuriy Glukhov)
- Raise group avatar filesize limit to 200kb
- OAuth applications feature
- Show user SSH keys in admin area
- Developer can push to protected branches option
- Set project path instead of project name in create form
-
-
- Updates to the messages returned by API (sponsored by O'Reilly Media)
- New UI layout with side navigation
-
-
- OAuth applications feature
-
- Add alert message in case of outdated browser (IE < 10)
-
- Set project path instead of project name in create form
- Added API support for sorting projects
- Update gitlab_git to version 7.0.0.rc13
-
-
- New side navigation
-
-
-
-
-
-
-
-
-
-
-
-
-
- Change some of application settings on fly in admin area UI
- Redesign signin/signup pages
- Close standard input in Gitlab::Popen.popen
v 7.6.0
- Fork repository to groups
......@@ -41,8 +65,15 @@ v 7.6.0
- Possibility to create Milestones or Labels when Issues are disabled
- Fix bug with showing gpg signature in tag
v 7.5.3
- Bump gitlab_git to 7.0.0.rc12 (includes Rugged 0.21.2)
v 7.5.2
- Don't log Sidekiq arguments by default
- Fix restore of wiki repositories from backups
v 7.5.1
- Add missing timestamps to 'members' table
v 7.5.0
- API: Add support for Hipchat (Kevin Houdebert)
......@@ -62,7 +93,7 @@ v 7.5.0
- Performance improvements
- Fix post-receive issue for projects with deleted forks
- New gitlab-shell version with custom hooks support
- Improve code
- Improve code
- GitLab CI 5.2+ support (does not support older versions)
- Fixed bug when you can not push commits starting with 000000 to protected branches
- Added a password strength indicator
......
......@@ -32,9 +32,12 @@ gem 'omniauth-kerberos'
gem 'doorkeeper', '2.0.1'
gem "rack-oauth2", "~> 1.0.5"
# Browser detection
gem "browser"
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", '7.0.0.rc12'
gem "gitlab_git", '7.0.0.rc13'
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
......@@ -93,7 +96,7 @@ gem "github-markup"
gem 'redcarpet', '~> 3.1.2'
gem 'RedCloth'
gem 'rdoc', '~>3.6'
gem 'org-ruby', '= 0.9.9'
gem 'org-ruby', '= 0.9.12'
gem 'creole', '~>0.3.6'
gem 'wikicloth', '=0.8.1'
gem 'asciidoctor', '= 0.1.4'
......
......@@ -50,6 +50,7 @@ GEM
debug_inspector (>= 0.0.1)
bootstrap-sass (3.0.3.0)
sass (~> 3.2)
browser (0.7.2)
builder (3.2.2)
capybara (2.2.1)
mime-types (>= 1.16)
......@@ -123,7 +124,7 @@ GEM
equalizer (0.0.8)
erubis (2.7.0)
escape_utils (0.2.4)
eventmachine (1.0.3)
eventmachine (1.0.4)
excon (0.32.1)
execjs (2.0.2)
expression_parser (0.9.0)
......@@ -182,7 +183,7 @@ GEM
mime-types (~> 1.19)
gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1)
gitlab_git (7.0.0.rc12)
gitlab_git (7.0.0.rc13)
activesupport (~> 4.0)
charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0)
......@@ -280,7 +281,7 @@ GEM
kaminari (0.15.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.8.1)
kgio (2.9.2)
launchy (2.4.2)
addressable (~> 2.3)
letter_opener (1.1.2)
......@@ -343,7 +344,7 @@ GEM
omniauth-twitter (1.0.1)
multi_json (~> 1.3)
omniauth-oauth (~> 1.0)
org-ruby (0.9.9)
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
pg (0.15.1)
......@@ -409,7 +410,7 @@ GEM
activesupport (= 4.1.1)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
raindrops (0.12.0)
raindrops (0.13.0)
rake (10.3.2)
raphael-rails (2.1.2)
rb-fsevent (0.9.3)
......@@ -619,6 +620,7 @@ DEPENDENCIES
better_errors
binding_of_caller
bootstrap-sass (~> 3.0)
browser
capybara (~> 2.2.1)
carrierwave
coffee-rails
......@@ -646,7 +648,7 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1)
gitlab_git (= 7.0.0.rc12)
gitlab_git (= 7.0.0.rc13)
gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.2.0)
gollum-lib (~> 3.0.0)
......@@ -681,7 +683,7 @@ DEPENDENCIES
omniauth-kerberos
omniauth-shibboleth
omniauth-twitter
org-ruby (= 0.9.9)
org-ruby (= 0.9.12)
pg
poltergeist (~> 1.5.1)
pry
......
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,mailer,system_hook,project_web_hook,common,default,gitlab_shell
worker: bundle exec sidekiq -q post_receive -q mailer -q system_hook -q project_web_hook -q gitlab_shell -q common -q default
7.6.0.pre-ee
7.7.0.pre-ee
$ ->
$(":checkbox").change ->
name = $(this).attr("name")
if name == "developers_can_push"
id = $(this).val()
checked = $(this).is(":checked")
url = $(this).data("url")
$.ajax
type: "PUT"
url: url
dataType: "json"
data:
id: id
developers_can_push: checked
success: ->
new Flash("Branch updated.", "notice")
location.reload true
error: ->
new Flash("Failed to update branch!", "alert")
......@@ -207,24 +207,16 @@ li.note {
}
}
.no-ssh-key-message {
padding: 10px 0;
background: #C67;
margin: 0;
color: #FFF;
margin-top: -1px;
.browser-alert {
padding: 10px;
text-align: center;
background: #C67;
color: #fff;
font-weight: bold;
a {
color: #fff;
text-decoration: underline;
}
.links-xs {
text-align: center;
font-size: 16px;
padding: 5px;
}
}
.warning_message {
......@@ -282,7 +274,7 @@ img.emoji {
}
.navless-container {
margin-top: 20px;
margin-top: 68px;
}
.description-block {
......@@ -309,11 +301,17 @@ table {
.dashboard-intro-icon {
float: left;
text-align: center;
font-size: 32px;
color: #AAA;
padding: 5px 0;
width: 50px;
min-height: 100px;
width: 60px;
}
.dashboard-intro-text {
display: inline-block;
margin-left: -60px;
padding-left: 60px;
width: 100%;
}
.broadcast-message {
......@@ -364,3 +362,9 @@ table {
.task-status {
margin-left: 10px;
}
#nprogress .spinner {
top: auto !important;
bottom: 20px !important;
left: 20px !important;
}
......@@ -31,7 +31,12 @@ fieldset legend {
margin-bottom: 18px;
background-color: whitesmoke;
border-top: 1px solid #e5e5e5;
padding-left: 17%;
}
@media (min-width: $screen-sm-min) {
.form-actions {
padding-left: 17%;
}
}
label {
......@@ -88,7 +93,8 @@ label {
@include box-shadow(none);
}
.issuable-description {
.issuable-description,
.wiki-content {
margin-top: 35px;
}
......
......@@ -65,6 +65,7 @@
.edit_note,
.issuable-description,
.milestone-description,
.wiki-content,
.merge-request-form {
.nav-tabs {
margin-bottom: 0;
......
......@@ -46,4 +46,4 @@ $deleted: #f77;
/**
* NProgress customize
*/
$nprogress-color: #3498db;
$nprogress-color: #c0392b;
......@@ -145,8 +145,12 @@
* Last push widget
*/
.event-last-push {
overflow: auto;
.event-last-push-text {
@include str-truncated(75%);
@include str-truncated(100%);
float:left;
margin-right: -150px;
padding-right: 150px;
line-height: 24px;
}
}
......
......@@ -4,9 +4,13 @@
*/
header {
&.navbar-gitlab {
z-index: 100;
margin-bottom: 0;
min-height: 40px;
border: none;
position: fixed;
top: 0;
width: 100%;
.navbar-inner {
filter: none;
......@@ -82,8 +86,6 @@ header {
}
}
z-index: 10;
.container {
width: 100% !important;
padding-left: 0px;
......
/* Login Page */
.login-page {
h1 {
font-size: 3em;
font-weight: 200;
.container {
max-width: 960px;
}
.login-box{
padding: 0 15px;
.navbar-gitlab .container {
max-width: none;
}
.login-heading h3 {
font-weight: 300;
line-height: 2;
}
.brand-holder {
font-size: 18px;
line-height: 1.5;
.login-footer {
margin-top: 10px;
p {
color: #888;
}
.btn {
padding: 12px !important;
@extend .btn-block;
h1:first-child {
font-weight: normal;
margin-bottom: 30px;
}
}
.brand-image {
img {
max-width: 100%;
margin-bottom: 20px;
margin-bottom: 30px;
}
&.default-brand-image {
margin: 0 80px;
a {
font-weight: bold;
}
}
.login-logo {
margin: 10px 0 30px 0;
display: block;
.login-box{
background: #fafafa;
border-radius: 10px;
box-shadow: 0 0px 2px #CCC;
padding: 15px;
.login-heading h3 {
font-weight: 300;
line-height: 1.5;
margin: 0;
display: none;
}
.login-footer {
margin-top: 10px;
}
a.forgot {
float: right;
padding-top: 6px
}
.nav .active a {
background: transparent;
}
}
.form-control {
background-color: #F5F5F5;
font-size: 16px;
padding: 14px 10px;
font-size: 14px;
padding: 10px 8px;
width: 100%;
height: auto;
......@@ -68,11 +86,6 @@
}
}
.login-box a.forgot {
float: right;
padding-top: 6px
}
.devise-errors {
h2 {
font-size: 14px;
......@@ -80,7 +93,19 @@
}
}
.brand-holder {
border-right: 1px solid #EEE;
.remember-me {
margin-top: -10px;
label {
font-weight: normal;
}
}
}
@media (max-width: $screen-xs-max) {
.login-page {
.col-sm-5.pull-right {
float: none !important;
}
}
}
......@@ -11,10 +11,27 @@
}
}
.accept-group {
label {
margin: 5px;
.accept-merge-holder {
margin-top: 5px;
.accept-action {
display: inline-block;
.accept_merge_request {
padding: 10px 20px;
}
}
.accept-control {
display: inline-block;
margin-left: 20px;
padding: 10px 0;
line-height: 20px;
font-weight: bold;
.checkbox {
margin: 0;
}
}
}
}
......@@ -170,7 +187,3 @@
.merge-request-show-labels .label {
padding: 6px 10px;
}
.mr-commits .commit {
padding: 10px 15px;
}
......@@ -62,6 +62,7 @@ ul.notes {
}
.note-body {
@include md-typography;
overflow: auto;
}
.note-header {
padding-bottom: 3px;
......
......@@ -308,3 +308,10 @@ ul.nav.nav-projects-tabs {
display: none;
}
}
table.table.protected-branches-list tr.no-border {
th, td {
border: 0;
}
}
......@@ -3,6 +3,7 @@
}
.sidebar-wrapper {
z-index: 99;
overflow-y: auto;
background: #F5F5F5;
}
......@@ -11,6 +12,7 @@
width: 100%;
padding: 15px;
background: #FFF;
margin-top: 48px;
}
.nav-sidebar {
......@@ -85,15 +87,7 @@
padding-left: 0px;
li {
line-height: 28px;
font-size: 12px;
list-style: none;
a {
padding: 5px 15px;
font-size: 12px;
padding-left: 20px;
}
}
}
......@@ -104,10 +98,11 @@
.sidebar-wrapper {
width: 250px;
position: absolute;
position: fixed;
left: 250px;
height: 100%;
margin-left: -250px;
border-right: 1px solid #EAEAEA;
.nav-sidebar {
margin-top: 20px;
......@@ -119,7 +114,6 @@
.content-wrapper {
padding: 20px;
border-left: 1px solid #EAEAEA;
}
}
......@@ -130,14 +124,16 @@
.sidebar-wrapper {
width: 52px;
position: absolute;
left: 50px;
position: fixed;
top: 0;
left: 0;
height: 100%;
margin-left: -50px;
border-right: 1px solid #EAEAEA;
overflow-x: hidden;
.nav-sidebar {
margin-top: 20px;
position: fixed;
position: absolute;
top: 45px;
width: 52px;
......
class Admin::ApplicationSettingsController < Admin::ApplicationController
before_filter :set_application_setting
def show
end
def update
if @application_setting.update_attributes(application_setting_params)
redirect_to admin_application_settings_path,
notice: 'Application settings saved successfully'
else
render :show
end
end
private
def set_application_setting
@application_setting = ApplicationSetting.current
end
def application_setting_params
params.require(:application_setting).permit(
:default_projects_limit,
:signup_enabled,
:signin_enabled,
:gravatar_enabled,
:sign_in_text,
)
end
end
class Admin::KeysController < Admin::ApplicationController
before_filter :user, only: [:show, :destroy]
def show
@key = user.keys.find(params[:id])
respond_to do |format|
format.html
format.js { render nothing: true }
end
end
def destroy
key = user.keys.find(params[:id])
respond_to do |format|
if key.destroy
format.html { redirect_to [:admin, user], notice: 'User key was successfully removed.' }
else
format.html { redirect_to [:admin, user], alert: 'Failed to remove user key.' }
end
end
end
protected
def user
@user ||= User.find_by!(username: params[:user_id])
end
def key_params
params.require(:user_id, :id)
end
end
......@@ -11,6 +11,7 @@ class Admin::UsersController < Admin::ApplicationController
def show
@personal_projects = user.personal_projects
@joined_projects = user.projects.joined(@user)
@keys = user.keys.order('id DESC')
end
def new
......@@ -118,7 +119,7 @@ class Admin::UsersController < Admin::ApplicationController
:email, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key,
:projects_limit, :can_create_group, :admin
:projects_limit, :can_create_group, :admin, :key_id
)
end
end
require 'gon'
class ApplicationController < ActionController::Base
include Gitlab::CurrentSettings
before_filter :authenticate_user_from_token!
before_filter :authenticate_user!
before_filter :reject_blocked!
......@@ -13,7 +15,7 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :abilities, :can?
helper_method :abilities, :can?, :current_application_settings
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
......@@ -263,10 +265,6 @@ class ApplicationController < ActionController::Base
# or improve current implementation to filter only issues you
# created or assigned or mentioned
#@filter_params[:authorized_only] = true
unless @filter_params[:assignee_id]
@filter_params[:assignee_id] = current_user.id
end
end
@filter_params
......
......@@ -11,7 +11,7 @@ class Projects::MilestonesController < Projects::ApplicationController
respond_to :html
def index
@milestones = case params[:f]
@milestones = case params[:state]
when 'all'; @project.milestones.order("state, due_date DESC")
when 'closed'; @project.milestones.closed.order("due_date DESC")
else @project.milestones.active.order("due_date ASC")
......
......@@ -15,6 +15,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
redirect_to project_protected_branches_path(@project)
end
def update
protected_branch = @project.protected_branches.find(params[:id])
if protected_branch &&
protected_branch.update_attributes(
developers_can_push: params[:developers_can_push]
)
respond_to do |format|
format.json { render :json => protected_branch, status: :ok }
end
else
respond_to do |format|
format.json { render json: protected_branch.errors, status: :unprocessable_entity }
end
end
end
def destroy
@project.protected_branches.find(params[:id]).destroy
......@@ -27,6 +45,6 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
private
def protected_branch_params
params.require(:protected_branch).permit(:name)
params.require(:protected_branch).permit(:name, :developers_can_push)
end
end
......@@ -42,7 +42,7 @@ class Projects::ServicesController < Projects::ApplicationController
:title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound, :bamboo_url, :username, :password,
:build_key, :server
:build_key, :server, :teamcity_url, :build_type
)
end
end
......@@ -26,7 +26,9 @@ class RegistrationsController < Devise::RegistrationsController
private
def signup_enabled?
redirect_to new_user_session_path unless Gitlab.config.gitlab.signup_enabled
unless current_application_settings.signup_enabled?
redirect_to(new_user_session_path)
end
end
def sign_up_params
......
class SessionsController < Devise::SessionsController
def new
redirect_path = if request.referer.present? && (params['redirect_to_referer'] == 'yes')
referer_uri = URI(request.referer)
if referer_uri.host == Gitlab.config.gitlab.host
referer_uri.path
else
request.fullpath
end
else
request.fullpath
end
redirect_path =
if request.referer.present? && (params['redirect_to_referer'] == 'yes')
referer_uri = URI(request.referer)
if referer_uri.host == Gitlab.config.gitlab.host
referer_uri.path
else
request.fullpath
end
else
request.fullpath
end
# Prevent a 'you are already signed in' message directly after signing:
# we should never redirect to '/users/sign_in' after signing in successfully.
......
......@@ -293,4 +293,21 @@ module ApplicationHelper
path << "?#{options.to_param}"
path
end
def outdated_browser?
browser.ie? && browser.version.to_i < 10
end
def path_to_key(key, admin = false)
if admin
admin_user_key_path(@user, key)
else
profile_key_path(key)
end
end
def redirect_from_root?
request.env['rack.session']['user_return_to'] ==
'/'
end
end
module ApplicationSettingsHelper
def gravatar_enabled?
current_application_settings.gravatar_enabled?
end
def signup_enabled?
current_application_settings.signup_enabled?
end
def signin_enabled?
current_application_settings.signin_enabled?
end
def extra_sign_in_text
current_application_settings.sign_in_text
end
end
module DashboardHelper
def entities_per_project(project, entity)
case entity.to_sym
when :issue then @issues.where(project_id: project.id)
when :merge_request then @merge_requests.where(target_project_id: project.id)
else
[]
end.count
end
def projects_dashboard_filter_path(options={})
exist_opts = {
sort: params[:sort],
scope: params[:scope],
group: params[:group],
tag: params[:tag],
visibility_level: params[:visibility_level],
}
options = exist_opts.merge(options)
......@@ -22,32 +15,11 @@ module DashboardHelper
path
end
def assigned_entities_count(current_user, entity, scope = nil)
items = current_user.send('assigned_' + entity.pluralize)
get_count(items, scope)
end
def authored_entities_count(current_user, entity, scope = nil)
items = current_user.send(entity.pluralize)
get_count(items, scope)
def assigned_issues_dashboard_path
issues_dashboard_path(assignee_id: current_user.id)
end
def authorized_entities_count(current_user, entity, scope = nil)
items = entity.classify.constantize
get_count(items, scope, true, current_user)
end
protected
def get_count(items, scope, get_authorized = false, current_user = nil)
items = items.opened
if scope.kind_of?(Group)
items = items.of_group(scope)
elsif scope.kind_of?(Project)
items = items.of_projects(scope)
elsif get_authorized
items = items.of_projects(current_user.authorized_projects)
end
items.count
def assigned_mrs_dashboard_path
merge_requests_dashboard_path(assignee_id: current_user.id)
end
end
......@@ -33,18 +33,6 @@ module GroupsHelper
title
end
def group_filter_path(entity, options={})
exist_opts = {
status: params[:status]
}
options = exist_opts.merge(options)
path = request.path
path << "?#{options.to_param}"
path
end
def group_settings_page?
if current_controller?('groups')
current_action?('edit') || current_action?('projects')
......
module MilestonesHelper
def milestones_filter_path(opts = {})
if @project
project_milestones_path(@project, opts)
elsif @group
group_milestones_path(@group, opts)
end
end
end
......@@ -14,6 +14,6 @@ module ProfileHelper
end
def show_profile_remove_tab?
gitlab_config.signup_enabled
signup_enabled?
end
end
class ApplicationSetting < ActiveRecord::Base
def self.current
ApplicationSetting.last
end
def self.create_from_defaults
create(
default_projects_limit: Settings.gitlab['default_projects_limit'],
signup_enabled: Settings.gitlab['signup_enabled'],
signin_enabled: Settings.gitlab['signin_enabled'],
gravatar_enabled: Settings.gravatar['enabled'],
sign_in_text: Settings.extra['sign_in_text'],
)
end
end
......@@ -174,7 +174,7 @@ class Event < ActiveRecord::Base
def valid_push?
data[:ref] && ref_name.present?
rescue => ex
rescue
false
end
......
......@@ -24,7 +24,7 @@ class Group < Namespace
has_many :ldap_group_links, foreign_key: 'group_id', dependent: :destroy
validate :avatar_type, if: ->(user) { user.avatar_changed? }
validates :avatar, file_size: { maximum: 100.kilobytes.to_i }
validates :avatar, file_size: { maximum: 200.kilobytes.to_i }
mount_uploader :avatar, AttachmentUploader
......
......@@ -48,7 +48,7 @@ class WebHook < ActiveRecord::Base
verify: false,
basic_auth: auth)
end
rescue SocketError, Errno::ECONNREFUSED => e
rescue SocketError, Errno::ECONNREFUSED, Net::OpenTimeout => e
logger.error("WebHook Error => #{e}")
false
end
......
......@@ -192,7 +192,9 @@ class MergeRequest < ActiveRecord::Base
end
def automerge!(current_user, commit_message = nil)
MergeRequests::AutoMergeService.new.execute(self, current_user, commit_message)
MergeRequests::AutoMergeService.
new(target_project, current_user).
execute(self, commit_message)
end
def open?
......
......@@ -6,12 +6,13 @@ class Notification
N_PARTICIPATING = 1
N_WATCH = 2
N_GLOBAL = 3
N_MENTION = 4
attr_accessor :target
class << self
def notification_levels
[N_DISABLED, N_PARTICIPATING, N_WATCH]
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_MENTION]
end
def options_with_labels
......@@ -19,12 +20,13 @@ class Notification
disabled: N_DISABLED,
participating: N_PARTICIPATING,
watch: N_WATCH,
mention: N_MENTION,
global: N_GLOBAL
}
end
def project_notification_levels
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL]
[N_DISABLED, N_PARTICIPATING, N_WATCH, N_GLOBAL, N_MENTION]
end
end
......@@ -48,6 +50,10 @@ class Notification
target.notification_level == N_GLOBAL
end
def mention?
target.notification_level == N_MENTION
end
def level
target.notification_level
end
......
......@@ -69,6 +69,7 @@ class Project < ActiveRecord::Base
has_one :jenkins_service, dependent: :destroy
has_one :buildbox_service, dependent: :destroy
has_one :bamboo_service, dependent: :destroy
has_one :teamcity_service, dependent: :destroy
has_one :pushover_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
......@@ -321,7 +322,8 @@ class Project < ActiveRecord::Base
end
def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack jira jenkins pushover buildbox bamboo)
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla
emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira jenkins)
end
def gitlab_ci?
......@@ -485,6 +487,10 @@ class Project < ActiveRecord::Base
protected_branches_names.include?(branch_name)
end
def developers_can_push_to_protected_branch?(branch_name)
protected_branches.any? { |pb| pb.name == branch_name && pb.developers_can_push }
end
def forked?
!(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
end
......
......@@ -35,7 +35,7 @@ class HipchatService < Service
{ type: 'text', name: 'token', placeholder: '' },
{ type: 'text', name: 'room', placeholder: '' },
{ type: 'text', name: 'server',
placeholder: 'Leave blank for default. https://chat.hipchat.com' }
placeholder: 'Leave blank for default. https://hipchat.example.com' }
]
end
......@@ -47,7 +47,7 @@ class HipchatService < Service
def gate
options = { api_version: 'v2' }
options[:server_url] = server unless server.nil?
options[:server_url] = server unless server.blank?
@gate ||= HipChat::Client.new(token, options)
end
......
require 'slack-notifier'
class SlackMessage
attr_reader :after
attr_reader :before
attr_reader :commits
attr_reader :project_name
attr_reader :project_url
attr_reader :ref
attr_reader :username
def initialize(params)
@after = params.fetch(:after)
@before = params.fetch(:before)
......@@ -23,14 +31,6 @@ class SlackMessage
private
attr_reader :after
attr_reader :before
attr_reader :commits
attr_reader :project_name
attr_reader :project_url
attr_reader :ref
attr_reader :username
def message
if new_branch?
new_branch_message
......
class TeamcityService < CiService
include HTTParty
prop_accessor :teamcity_url, :build_type, :username, :password
validates :teamcity_url, presence: true,
format: { with: URI::regexp }, if: :activated?
validates :build_type, presence: true, if: :activated?
validates :username, presence: true,
if: ->(service) { service.password? }, if: :activated?
validates :password, presence: true,
if: ->(service) { service.username? }, if: :activated?
attr_accessor :response
after_save :compose_service_hook, if: :activated?
def compose_service_hook
hook = service_hook || build_service_hook
hook.save
end
def title
'JetBrains TeamCity CI'
end
def description
'A continuous integration and build server'
end
def help
'The build configuration in Teamcity must use the build format '\
'number %build.vcs.number% '\
'you will also want to configure monitoring of all branches so merge '\
'requests build, that setting is in the vsc root advanced settings.'
end
def to_param
'teamcity'
end
def fields
[
{ type: 'text', name: 'teamcity_url',
placeholder: 'TeamCity root URL like https://teamcity.example.com' },
{ type: 'text', name: 'build_type',
placeholder: 'Build configuration ID' },
{ type: 'text', name: 'username',
placeholder: 'A user with permissions to trigger a manual build' },
{ type: 'password', name: 'password' },
]
end
def build_info(sha)
url = URI.parse("#{teamcity_url}/httpAuth/app/rest/builds/"\
"branch:unspecified:any,number:#{sha}")
auth = {
username: username,
password: password,
}
@response = HTTParty.get("#{url}", verify: false, basic_auth: auth)
end
def build_page(sha)
build_info(sha) if @response.nil? || !@response.code
if @response.code != 200
# If actual build link can't be determined,
# send user to build summary page.
"#{teamcity_url}/viewLog.html?buildTypeId=#{build_type}"
else
# If actual build link is available, go to build result page.
built_id = @response['build']['id']
"#{teamcity_url}/viewLog.html?buildId=#{built_id}"\
"&buildTypeId=#{build_type}"
end
end
def commit_status(sha)
build_info(sha) if @response.nil? || !@response.code
return :error unless @response.code == 200 || @response.code == 404
status = if @response.code == 404
'Pending'
else
@response['build']['status']
end
if status.include?('SUCCESS')
'success'
elsif status.include?('FAILURE')
'failed'
elsif status.include?('Pending')
'pending'
else
:error
end
end
def execute(data)
auth = {
username: username,
password: password,
}
branch = data[:ref]
self.class.post("#{teamcity_url}/httpAuth/app/rest/buildQueue",
body: "<build branchName=\"#{branch}\">"\
"<buildType id=\"#{build_type}\"/>"\
'</build>',
headers: { 'Content-type' => 'application/xml' },
basic_auth: auth
)
end
end
......@@ -51,14 +51,15 @@ require 'file_size_validator'
class User < ActiveRecord::Base
include Gitlab::ConfigHelper
extend Gitlab::ConfigHelper
include TokenAuthenticatable
extend Gitlab::ConfigHelper
extend Gitlab::CurrentSettings
default_value_for :admin, false
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
default_value_for :projects_limit, gitlab_config.default_projects_limit
default_value_for :projects_limit, current_application_settings.default_projects_limit
default_value_for :theme_id, gitlab_config.default_theme
devise :database_authenticatable, :lockable, :async,
......
class BaseService
include Gitlab::CurrentSettings
attr_accessor :project, :current_user, :params
def initialize(project, user, params = {})
......@@ -29,6 +31,10 @@ class BaseService
SystemHooksService.new
end
def current_application_settings
ApplicationSetting.current
end
private
def error(message)
......
class GravatarService
include Gitlab::CurrentSettings
def execute(email, size = nil)
if gravatar_config.enabled && email.present?
if current_application_settings.gravatar_enabled? && email.present?
size = 40 if size.nil? || size <= 0
sprintf gravatar_url,
......
......@@ -5,15 +5,16 @@ module MergeRequests
# mark merge request as merged and execute all hooks and notifications
# Called when you do merge via GitLab UI
class AutoMergeService < BaseMergeService
def execute(merge_request, current_user, commit_message)
def execute(merge_request, commit_message)
merge_request.lock_mr
if Gitlab::Satellite::MergeAction.new(current_user, merge_request).merge!(commit_message)
merge_request.merge
notification.merge_mr(merge_request, current_user)
notification_service.merge_mr(merge_request, current_user)
create_merge_event(merge_request, current_user)
execute_project_hooks(merge_request)
create_note(merge_request)
execute_hooks(merge_request)
true
else
......
module MergeRequests
class BaseMergeService
class BaseMergeService < MergeRequests::BaseService
private
def notification
NotificationService.new
end
def create_merge_event(merge_request, current_user)
EventCreateService.new.merge_mr(merge_request, current_user)
end
def execute_project_hooks(merge_request)
if merge_request.project
hook_data = merge_request.to_hook_data(current_user)
merge_request.project.execute_hooks(hook_data, :merge_request_hooks)
end
end
end
end
......@@ -13,7 +13,7 @@ module MergeRequests
merge_request.target_branch ||= merge_request.target_project.default_branch
unless merge_request.target_branch && merge_request.source_branch
return build_failed(merge_request, "You must select source and target branches")
return build_failed(merge_request, nil)
end
# Generate suggested MR title based on source branch name
......@@ -62,7 +62,7 @@ module MergeRequests
end
def build_failed(merge_request, message)
merge_request.errors.add(:base, message)
merge_request.errors.add(:base, message) unless message.nil?
merge_request.compare_commits = []
merge_request.can_be_created = false
merge_request
......
......@@ -6,12 +6,13 @@ module MergeRequests
# Called when you do merge via command line and push code
# to target branch
class MergeService < BaseMergeService
def execute(merge_request, current_user, commit_message)
def execute(merge_request, commit_message)
merge_request.merge
notification.merge_mr(merge_request, current_user)
notification_service.merge_mr(merge_request, current_user)
create_merge_event(merge_request, current_user)
execute_project_hooks(merge_request)
create_note(merge_request)
execute_hooks(merge_request)
true
rescue
......
......@@ -32,7 +32,9 @@ module MergeRequests
merge_requests.uniq.select(&:source_project).each do |merge_request|
MergeRequests::MergeService.new.execute(merge_request, @current_user, nil)
MergeRequests::MergeService.
new(merge_request.target_project, @current_user).
execute(merge_request, nil)
end
end
......
module Notes
class UpdateService < BaseService
def execute
note = project.notes.find(params[:note_id])
note.note = params[:note]
if note.save
notification_service.new_note(note)
# Skip system notes, like status changes and cross-references.
unless note.system
event_service.leave_note(note, note.author)
# Create a cross-reference note if this Note contains GFM that
# names an issue, merge request, or commit.
note.references.each do |mentioned|
Note.create_cross_reference_note(mentioned, note.noteable,
note.author, note.project)
end
end
end
note
end
end
end
......@@ -144,6 +144,10 @@ class NotificationService
# Merge project watchers
recipients = recipients.concat(project_watchers(note.project)).compact.uniq
# Reject mention users unless mentioned in comment
recipients = reject_mention_users(recipients - note.mentioned_users, note.project)
recipients = recipients + note.mentioned_users
# Reject mutes users
recipients = reject_muted_users(recipients, note.project)
......@@ -285,13 +289,39 @@ class NotificationService
end
end
# Remove users with notification level 'Mentioned'
def reject_mention_users(users, project = nil)
users = users.to_a.compact.uniq
users.reject do |user|
next user.notification.mention? unless project
tm = project.project_members.find_by(user_id: user.id)
if !tm && project.group
tm = project.group.group_members.find_by(user_id: user.id)
end
# reject users who globally set mention notification and has no membership
next user.notification.mention? unless tm
# reject users who set mention notification in project
next true if tm.notification.mention?
# reject users who have N_MENTION in project and disabled in global settings
tm.notification.global? && user.notification.mention?
end
end
def new_resource_email(target, project, method)
if target.respond_to?(:participants)
recipients = target.participants
else
recipients = []
end
recipients = reject_muted_users(recipients, project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(target.author)
......@@ -302,6 +332,7 @@ class NotificationService
def close_resource_email(target, project, current_user, method)
recipients = reject_muted_users([target.author, target.assignee], project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(current_user)
......@@ -320,6 +351,7 @@ class NotificationService
# reject users with disabled notifications
recipients = reject_muted_users(recipients, project)
recipients = reject_mention_users(recipients, project)
# Reject me from recipients if I reassign an item
recipients.delete(current_user)
......@@ -331,6 +363,7 @@ class NotificationService
def reopen_resource_email(target, project, current_user, method, status)
recipients = reject_muted_users([target.author, target.assignee], project)
recipients = reject_mention_users(recipients, project)
recipients = recipients.concat(project_watchers(project)).uniq
recipients.delete(current_user)
......
= form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f|
- if @application_setting.errors.any?
#error_explanation
.alert.alert-danger
- @application_setting.errors.full_messages.each do |msg|
%p= msg
%fieldset
%legend Features
.form-group
= f.label :signup_enabled, class: 'control-label'
.col-sm-10
= f.check_box :signup_enabled, class: 'checkbox'
.form-group
= f.label :signin_enabled, class: 'control-label'
.col-sm-10
= f.check_box :signin_enabled, class: 'checkbox'
.form-group
= f.label :gravatar_enabled, class: 'control-label'
.col-sm-10
= f.check_box :gravatar_enabled, class: 'checkbox'
%fieldset
%legend Misc
.form-group
= f.label :default_projects_limit, class: 'control-label'
.col-sm-10
= f.number_field :default_projects_limit, class: 'form-control'
.form-group
= f.label :sign_in_text, class: 'control-label'
.col-sm-10
= f.text_area :sign_in_text, class: 'form-control'
.form-actions
= f.submit 'Save', class: 'btn btn-primary'
%h3.page-title Application settings
%hr
= render 'form'
......@@ -104,7 +104,7 @@
%p
Sign up
%span.light.pull-right
= boolean_to_icon gitlab_config.signup_enabled
= boolean_to_icon signup_enabled?
%p
LDAP
%span.light.pull-right
......@@ -112,7 +112,7 @@
%p
Gravatar
%span.light.pull-right
= boolean_to_icon Gitlab.config.gravatar.enabled
= boolean_to_icon gravatar_enabled?
%p
OmniAuth
%span.light.pull-right
......
= render "profiles/keys/key_details", admin: true
......@@ -20,6 +20,8 @@
%a{"data-toggle" => "tab", href: "#groups"} Groups
%li
%a{"data-toggle" => "tab", href: "#projects"} Projects
%li
%a{"data-toggle" => "tab", href: "#ssh-keys"} SSH keys
.tab-content
#account.tab-pane.active
......@@ -217,3 +219,5 @@
- if tm.respond_to? :project
= link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do
%i.fa.fa-times
#ssh-keys.tab-pane
= render 'profiles/keys/key_table', admin: true
%fieldset
%ul.nav.nav-pills.nav-stacked
= nav_tab :scope, nil do
= link_to projects_dashboard_filter_path(scope: nil) do
All
%span.pull-right
= current_user.authorized_projects.count
= nav_tab :scope, 'personal' do
= link_to projects_dashboard_filter_path(scope: 'personal') do
Personal
%span.pull-right
= current_user.personal_projects.count
= nav_tab :scope, 'joined' do
= link_to projects_dashboard_filter_path(scope: 'joined') do
Joined
%span.pull-right
= current_user.authorized_projects.joined(current_user).count
= nav_tab :scope, 'owned' do
= link_to projects_dashboard_filter_path(scope: 'owned') do
Owned
%span.pull-right
= current_user.owned_projects.count
.dash-projects-filters.append-bottom-20
.pull-left.append-right-20
%ul.nav.nav-pills.nav-compact
= nav_tab :scope, nil do
= link_to projects_dashboard_filter_path(scope: nil) do
All
= nav_tab :scope, 'personal' do
= link_to projects_dashboard_filter_path(scope: 'personal') do
Personal
= nav_tab :scope, 'joined' do
= link_to projects_dashboard_filter_path(scope: 'joined') do
Joined
= nav_tab :scope, 'owned' do
= link_to projects_dashboard_filter_path(scope: 'owned') do
Owned
%fieldset
%legend Visibility
%ul.nav.nav-pills.nav-stacked.nav-small.visibility-filter
- Gitlab::VisibilityLevel.values.each do |level|
%li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(visibility_level: level) do
= visibility_level_icon(level)
= visibility_level_label(level)
.dropdown.inline.append-right-10
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-globe
%span.light Visibility:
- if params[:visibility_level].present?
= visibility_level_label(params[:visibility_level].to_i)
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to projects_dashboard_filter_path(visibility_level: nil) do
Any
- Gitlab::VisibilityLevel.values.each do |level|
%li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(visibility_level: level) do
= visibility_level_icon(level)
= visibility_level_label(level)
- if @groups.present?
%fieldset
%legend Groups
%ul.nav.nav-pills.nav-stacked.nav-small
- @groups.each do |group|
%li{ class: (group.name == params[:group]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(group: group.name) do
%i.fa.fa-folder-o
= group.name
%small.pull-right
= group.projects.count
- if @groups.present?
.dropdown.inline.append-right-10
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-group
%span.light Group:
- if params[:group].present?
= Group.find_by(name: params[:group]).name
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to projects_dashboard_filter_path(group: nil) do
Any
- @groups.each do |group|
%li{ class: (group.name == params[:group]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(group: group.name) do
= group.name
%small.pull-right
= group.projects.count
- if @tags.present?
%fieldset
%legend Tags
%ul.nav.nav-pills.nav-stacked.nav-small
- @tags.each do |tag|
%li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(scope: params[:scope], tag: tag.name) do
%i.fa.fa-tag
= tag.name
- if @tags.present?
.dropdown.inline.append-right-10
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%i.fa.fa-tags
%span.light Tags:
- if params[:tag].present?
= params[:tag]
- else
Any
%b.caret
%ul.dropdown-menu
%li
= link_to projects_dashboard_filter_path(tag: nil) do
Any
- @tags.each do |tag|
%li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(tag: tag.name) do
%i.fa.fa-tag
= tag.name
.pull-right
.dropdown.inline
%a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort:
- if @sort.present?
= @sort.humanize
- else
Name
%b.caret
%ul.dropdown-menu
%li
= link_to projects_dashboard_filter_path(sort: nil) do
Name
= link_to projects_dashboard_filter_path(sort: 'newest') do
= sort_title_recently_created
= link_to projects_dashboard_filter_path(sort: 'oldest') do
= sort_title_oldest_created
= link_to projects_dashboard_filter_path(sort: 'recently_updated') do
= sort_title_recently_updated
= link_to projects_dashboard_filter_path(sort: 'last_updated') do
= sort_title_oldest_updated
......@@ -4,7 +4,7 @@
%div
.dashboard-intro-icon
%i.fa.fa-bookmark-o
%div
.dashboard-intro-text
%p.slead
You don't have access to any projects right now.
%br
......@@ -24,7 +24,7 @@
%div
.dashboard-intro-icon
%i.fa.fa-users
%div
.dashboard-intro-text
%p.slead
You can create a group for several dependent projects.
%br
......@@ -38,7 +38,7 @@
%div
.dashboard-intro-icon
%i.fa.fa-globe
%div
.dashboard-intro-text
%p.slead
There are
%strong= @publicish_project_count
......
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "#{current_user.name} issues"
xml.link href: issues_dashboard_url(:atom, private_token: current_user.private_token), rel: "self", type: "application/atom+xml"
xml.link href: issues_dashboard_url(private_token: current_user.private_token), rel: "alternate", type: "text/html"
......
%h3.page-title
My Projects
.pull-right
.dropdown.inline
%a.dropdown-toggle.btn.btn-small{href: '#', "data-toggle" => "dropdown"}
%span.light sort:
- if @sort.present?
= @sort.humanize
- else
Name
%b.caret
%ul.dropdown-menu
%li
= link_to projects_dashboard_filter_path(sort: nil) do
Name
= link_to projects_dashboard_filter_path(sort: 'newest') do
= sort_title_recently_created
= link_to projects_dashboard_filter_path(sort: 'oldest') do
= sort_title_oldest_created
= link_to projects_dashboard_filter_path(sort: 'recently_updated') do
= sort_title_recently_updated
= link_to projects_dashboard_filter_path(sort: 'last_updated') do
= sort_title_oldest_updated
%p.light
All projects you have access to are listed here. Public projects are not included here unless you are a member
%hr
.row
.col-md-3.hidden-sm.hidden-xs.side-filters
= render "projects_filter"
.col-md-9
%ul.bordered-list.my-projects.top-list
- @projects.each do |project|
%li.my-project-row
%h4.project-title
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project_path(project), class: dom_class(project) do
= project.name_with_namespace
.side-filters
= render "projects_filter"
.dash-projects
%ul.bordered-list.my-projects.top-list
- @projects.each do |project|
%li.my-project-row
%h4.project-title
.project-access-icon
= visibility_level_icon(project.visibility_level)
= link_to project_path(project), class: dom_class(project) do
= project.name_with_namespace
- if project.forked_from_project
&nbsp;
%small
%i.fa.fa-code-fork
Forked from:
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
- if project.forked_from_project
&nbsp;
%small
%i.fa.fa-code-fork
Forked from:
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
- if current_user.can_leave_project?(project)
.pull-right
= link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do
%i.fa.fa-sign-out
Leave
.project-info
- if current_user.can_leave_project?(project)
.pull-right
- if project.archived?
%span.label
%i.fa.fa-archive
Archived
- project.tags.each do |tag|
%span.label.label-info
%i.fa.fa-tag
= tag.name
- if project.description.present?
%p= truncate project.description, length: 100
.last-activity
%span.light Last activity:
%span.date= project_last_activity(project)
= link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do
%i.fa.fa-sign-out
Leave
.project-info
.pull-right
- if project.archived?
%span.label
%i.fa.fa-archive
Archived
- project.tags.each do |tag|
%span.label.label-info
%i.fa.fa-tag
= tag.name
- if project.description.present?
%p= truncate project.description, length: 100
.last-activity
%span.light Last activity:
%span.date= project_last_activity(project)
- if @projects.blank?
%li
.nothing-here-block There are no projects here.
.bottom
= paginate @projects, theme: "gitlab"
- if @projects.blank?
%li
.nothing-here-block There are no projects here.
.bottom
= paginate @projects, theme: "gitlab"
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "Dashboard feed#{" - #{current_user.name}" if current_user.name.present?}"
xml.link href: dashboard_url(:atom), rel: "self", type: "application/atom+xml"
xml.link href: dashboard_url, rel: "alternate", type: "text/html"
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -2,7 +2,7 @@
= f.text_field :login, class: "form-control top", placeholder: "Username or Email", autofocus: "autofocus"
= f.password_field :password, class: "form-control bottom", placeholder: "Password"
- if devise_mapping.rememberable?
.clearfix.append-bottom-10
.remember-me
%label.checkbox.remember_me{for: "user_remember_me"}
= f.check_box :remember_me
%span Remember me
......
= form_tag(user_omniauth_callback_path(provider), id: 'new_ldap_user' ) do
= text_field_tag :username, nil, {class: "form-control top", placeholder: "LDAP Login", autofocus: "autofocus"}
= password_field_tag :password, nil, {class: "form-control bottom", placeholder: "Password"}
%br/
= button_tag "LDAP Sign in", class: "btn-save btn"
.login-box
.login-heading
%h3 Sign in
.login-body
- if standard_login_form_only?
%ul.nav.nav-tabs
- if ldap_enabled?
- @ldap_servers.each_with_index do |server, i|
%li{class: (:active if i.zero?)}
= link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
- if kerberos_enabled?
%li{class: (:active unless ldap_enabled?)}
= link_to "Kerberos", "#tab-kerberos", 'data-toggle' => 'tab'
- if gitlab_config.signin_enabled
%li
= link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
.tab-content
- if ldap_enabled?
- @ldap_servers.each_with_index do |server, i|
%div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
= render 'devise/sessions/new_ldap', provider: server['provider_name']
- if kerberos_enabled?
%div#tab-kerberos.tab-pane{class: (:active unless ldap_enabled?)}
= render 'devise/sessions/new_kerberos', provider: :kerberos
- if gitlab_config.signin_enabled
%div#tab-signin.tab-pane
= render 'devise/sessions/new_base'
%div
= render 'devise/shared/signin_box'
- elsif gitlab_config.signin_enabled
= render 'devise/sessions/new_base'
- else
%div
No authentication methods configured.
- if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?
.prepend-top-20
= render 'devise/shared/oauth_box'
= render 'devise/sessions/oauth_providers' if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?
- if signup_enabled?
.prepend-top-20
= render 'devise/shared/signup_box'
.login-footer
- if gitlab_config.signup_enabled
%p
%span.light
Don't have an account?
%strong
= link_to "Sign up", new_registration_path(resource_name)
%p
%span.light Did not receive confirmation email?
= link_to "Send again", new_confirmation_path(resource_name)
- if extra_config.has_key?('sign_in_text')
%hr
= markdown(extra_config.sign_in_text)
.clearfix.prepend-top-20
%p
%span.light Did not receive confirmation email?
= link_to "Send again", new_confirmation_path(resource_name)
- providers = additional_providers
- if providers.present?
.bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp;
.login-box{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with &nbsp;
- providers.each do |provider|
%span
- if default_providers.include?(provider)
......
.login-box
.login-heading
%h3 Sign in
.login-body
- if ldap_enabled?
%ul.nav.nav-tabs
- @ldap_servers.each_with_index do |server, i|
%li{class: (:active if i.zero?)}
= link_to server['label'], "#tab-#{server['provider_name']}", 'data-toggle' => 'tab'
- if kerberos_enabled?
%li{class: (:active unless ldap_enabled?)}
= link_to "Kerberos", "#tab-kerberos", 'data-toggle' => 'tab'
- if signin_enabled?
%li
= link_to 'Standard', '#tab-signin', 'data-toggle' => 'tab'
.tab-content
- @ldap_servers.each_with_index do |server, i|
%div.tab-pane{id: "tab-#{server['provider_name']}", class: (:active if i.zero?)}
= render 'devise/sessions/new_ldap', provider: server['provider_name']
- if kerberos_enabled?
%div#tab-kerberos.tab-pane{class: (:active unless ldap_enabled?)}
= render 'devise/sessions/new_kerberos', provider: :kerberos
- if signin_enabled?
%div#tab-signin.tab-pane
= render 'devise/sessions/new_base'
- elsif signin_enabled?
= render 'devise/sessions/new_base'
- else
%div
No authentication methods configured.
.login-box
.login-heading
%h3 Sign up
.login-body
= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
.devise-errors
= devise_error_messages!
%div
= f.text_field :name, class: "form-control top", placeholder: "Name", required: true
%div
= f.text_field :username, class: "form-control middle", placeholder: "Username", required: true
%div
= f.email_field :email, class: "form-control middle", placeholder: "Email", required: true
.form-group#password-strength
= f.password_field :password, class: "form-control bottom", id: "user_password_sign_up", placeholder: "Password", required: true
%div
= f.submit "Sign up", class: "btn-create btn"
= form_tag group_filter_path(entity), method: 'get' do
%fieldset
%ul.nav.nav-pills.nav-stacked
%li{class: ("active" if (params[:status] == 'active' || !params[:status]))}
= link_to group_filter_path(entity, status: 'active') do
Active
%li{class: ("active" if params[:status] == 'closed')}
= link_to group_filter_path(entity, status: 'closed') do
Closed
%li{class: ("active" if params[:status] == 'all')}
= link_to group_filter_path(entity, status: 'all') do
All
......@@ -2,18 +2,21 @@
= nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group) do
%i.fa.fa-pencil-square-o
Group
%span
Group
= nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group) do
%i.fa.fa-folder
Projects
%span
Projects
- if ldap_enabled?
= nav_link(controller: :ldap_group_links) do
= link_to group_ldap_group_links_path(@group) do
%i.fa.fa-exchange
LDAP Groups
%span
LDAP Groups
= nav_link(controller: :audit_events) do
= link_to group_audit_events_path(@group) do
%i.fa.fa-file-text-o
Audit Events
%span
Audit Events
......@@ -9,42 +9,38 @@
%hr
.row
.fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.fa.fa-list.fa-2x
.col-md-3.responsive-side
= render 'groups/filter', entity: 'milestone'
.col-md-9
.panel.panel-default
%ul.well-list
- if @group_milestones.blank?
%li
.nothing-here-block No milestones to show
- else
- @group_milestones.each do |milestone|
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
.pull-right
- if can?(current_user, :manage_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-close"
%h4
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
= render 'shared/milestones_filter'
.milestones
.panel.panel-default
%ul.well-list
- if @group_milestones.blank?
%li
.nothing-here-block No milestones to show
- else
- @group_milestones.each do |milestone|
%li{class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: dom_id(milestone.milestones.first) }
.pull-right
- if can?(current_user, :manage_group, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped btn-reopen"
- else
= link_to 'Close Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-small btn-close"
%h4
= link_to_gfm truncate(milestone.title, length: 100), group_milestone_path(@group, milestone.safe_title, title: milestone.title)
%div
%div
%div
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.progress.progress-info
.progress-bar{style: "width: #{milestone.percent_complete}%;"}
%div
%br
- milestone.projects.each do |project|
%span.label.label-default
= project.name
= paginate @group_milestones, theme: "gitlab"
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.issue_count, 'Issue'
&nbsp;
= link_to group_milestone_path(@group, milestone.safe_title, title: milestone.title) do
= pluralize milestone.merge_requests_count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete
.progress.progress-info
.progress-bar{style: "width: #{milestone.percent_complete}%;"}
%div
%br
- milestone.projects.each do |project|
%span.label.label-default
= project.name
= paginate @group_milestones, theme: "gitlab"
%h3.page-title
%h4.page-title
.issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" }
- if @group_milestone.closed?
Closed
- else
Open
Milestone #{@group_milestone.title}
.pull-right
- if can?(current_user, :manage_group, @group)
......@@ -7,46 +12,41 @@
- else
= link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-small btn-grouped btn-reopen"
%hr
- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active?
.alert.alert-success
%span All issues for this milestone are closed. You may close the milestone now.
.back-link
= link_to group_milestones_path(@group) do
&larr; To milestones list
.issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" }
.state.clearfix
.state-label
- if @group_milestone.closed?
Closed
- else
Open
%h4.title
= gfm escape_once(@group_milestone.title)
.description
- @group_milestone.milestones.each do |milestone|
%hr
%h4
= link_to "#{milestone.project.name} - #{milestone.title}", project_milestone_path(milestone.project, milestone)
%span.pull-right= milestone.expires_at
.description
%table.table
%thead
%tr
%th Project
%th Open issues
%th State
%th Due date
- @group_milestone.milestones.each do |milestone|
%tr
%td
= link_to "#{milestone.project.name}", project_milestone_path(milestone.project, milestone)
%td
= milestone.issues.opened.count
%td
- if milestone.closed?
%span.label.label-danger #{milestone.state}
= preserve do
- if milestone.description.present?
= milestone.description
.context
%p
Progress:
#{@group_milestone.closed_items_count} closed
&ndash;
#{@group_milestone.open_items_count} open
Closed
- else
Open
%td
= milestone.expires_at
.progress.progress-info
.progress-bar{style: "width: #{@group_milestone.percent_complete}%;"}
.context
%p.lead
Progress:
#{@group_milestone.closed_items_count} closed
&ndash;
#{@group_milestone.open_items_count} open
.progress.progress-info
.progress-bar{style: "width: #{@group_milestone.percent_complete}%;"}
%ul.nav.nav-tabs
%li.active
......
xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlnsmedia" => "http://search.yahoo.com/mrss/" do
xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://search.yahoo.com/mrss/" do
xml.title "Group feed - #{@group.name}"
xml.link href: group_path(@group, :atom), rel: "self", type: "application/atom+xml"
xml.link href: group_path(@group), rel: "alternate", type: "text/html"
......
......@@ -45,3 +45,5 @@
%li.hidden-xs
= link_to current_user, class: "profile-pic", id: 'profile-pic' do
= image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
= render 'shared/outdated_browser'
......@@ -12,11 +12,13 @@
%span.sr-only Toggle navigation
%i.fa.fa-bars
.pull-right.hidden-xs
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new'
- unless current_controller?('sessions')
.pull-right.hidden-xs
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-new'
.navbar-collapse.collapse
%ul.nav.navbar-nav
%li.visible-xs
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
.navbar-collapse.collapse
%ul.nav.navbar-nav
%li.visible-xs
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes')
= render 'shared/outdated_browser'
!!! 5
%html{ lang: "en"}
= render "layouts/head"
%body.ui_basic.login-page
.container
.content
.login-title
%h1= brand_title
%hr
.container
%body.ui_mars.login-page.application
= render "layouts/broadcast"
= render "layouts/public_head_panel", title: ''
.container.navless-container
.content
= render "layouts/flash"
.row
.col-md-7.brand-holder
- unless redirect_from_root?
= render "layouts/flash"
.row.prepend-top-20
.col-sm-5.pull-right
= yield
.col-sm-7.brand-holder.pull-left
%h1
= brand_title
- if brand_item
.brand-image
= brand_image
.brand_text
= brand_text
= brand_image
= brand_text
- else
.brand-image.default-brand-image.hidden-sm.hidden-xs
= image_tag 'brand_logo.png'
.brand_text.hidden-xs
%h2 Open source software to collaborate on code
%h3 Open source software to collaborate on code
%p.lead
Manage git repositories with fine grained access controls that keep your code secure.
Perform code reviews and enhance collaboration with merge requests.
Each project can also have an issue tracker and a wiki.
%p
Manage git repositories with fine grained access controls that keep your code secure.
Perform code reviews and enhance collaboration with merge requests.
Each project can also have an issue tracker and a wiki.
- if extra_sign_in_text.present?
= markdown(extra_sign_in_text)
.col-md-5
= yield
%hr
.container
.footer-links
......
......@@ -44,3 +44,8 @@
%i.fa.fa-image
%span
Appearance
= nav_link(controller: :application_settings) do
= link_to admin_application_settings_path do
%i.fa.fa-cogs
%span
Settings
......@@ -10,13 +10,13 @@
%span
Projects
= nav_link(path: 'dashboard#issues') do
= link_to issues_dashboard_path, class: 'shortcuts-issues' do
= link_to assigned_issues_dashboard_path, class: 'shortcuts-issues' do
%i.fa.fa-exclamation-circle
%span
Issues
%span.count= current_user.assigned_issues.opened.count
= nav_link(path: 'dashboard#merge_requests') do
= link_to merge_requests_dashboard_path, class: 'shortcuts-merge_requests' do
= link_to assigned_mrs_dashboard_path, class: 'shortcuts-merge_requests' do
%i.fa.fa-tasks
%span
Merge Requests
......
......@@ -7,7 +7,8 @@
= nav_link(controller: :accounts) do
= link_to profile_account_path do
%i.fa.fa-gear
Account
%span
Account
= nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do
= link_to applications_profile_path do
%i.fa.fa-cloud
......
......@@ -5,8 +5,5 @@
= render "layouts/broadcast"
= render "layouts/head_panel", title: project_title(@project)
= render "layouts/init_auto_complete"
- if can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
- @project_settings_nav = true
= render 'layouts/page', sidebar: 'layouts/nav/project'
......@@ -5,6 +5,4 @@
= render "layouts/broadcast"
= render "layouts/head_panel", title: project_title(@project)
= render "layouts/init_auto_complete"
- if can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
= render 'layouts/page', sidebar: 'layouts/nav/project'
......@@ -6,7 +6,9 @@
- @commits.each do |commit|
%li
%strong #{link_to commit.short_id, project_commit_url(@project, commit)}
%span by #{commit.author_name}
%div
%span by #{commit.author_name}
%i at #{commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")}
%pre #{commit.safe_message}
%h4 Changes:
......
%li
= link_to profile_key_path(key) do
%strong= key.title
%span
(#{key.fingerprint})
%span.cgray
added #{time_ago_with_tooltip(key.created_at)}
- unless key.is_a? LDAPKey
= link_to 'Remove', profile_key_path(key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
%tr
%td
= link_to path_to_key(key, is_admin) do
%strong= key.title
%td
%span
(#{key.fingerprint})
%td
%span.cgray
added #{time_ago_with_tooltip(key.created_at)}
%td
- unless key.is_a? LDAPKey
= link_to 'Remove', path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-small btn-remove delete-key pull-right"
- is_admin = defined?(admin) ? true : false
.row
.col-md-4
.panel.panel-default
.panel-heading
SSH Key
%ul.well-list
%li
%span.light Title:
%strong= @key.title
%li
%span.light Created on:
%strong= @key.created_at.stamp("Aug 21, 2011")
.col-md-8
%p
%span.light Fingerprint:
%strong= @key.fingerprint
%pre.well-pre
= @key.key
.pull-right
- unless @key.is_a? LDAPKey
= link_to 'Remove', path_to_key(@key, is_admin), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
- is_admin = defined?(admin) ? true : false
.panel.panel-default
- if @keys.any?
%table.table
%thead.panel-heading
%tr
%th Title
%th Fingerprint
%th Added at
%th
%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.
%h3.page-title
My SSH keys
My SSH keys (#{@keys.count})
.pull-right
= link_to "Add SSH Key", new_profile_key_path, class: "btn btn-new"
%p.light
......@@ -9,14 +9,4 @@
= link_to "generate it", help_page_path("ssh", "ssh")
%hr
.panel.panel-default
.panel-heading
SSH Keys (#{@keys.count})
%ul.well-list#keys-table
= render partial: "key", collection: @keys
- if @keys.blank?
%li
.nothing-here-block There are no SSH keys with access to your account.
= render 'key_table'
.row
.col-md-4
.panel.panel-default
.panel-heading
SSH Key
%ul.well-list
%li
%span.light Title:
%strong= @key.title
%li
%span.light Created on:
%strong= @key.created_at.stamp("Aug 21, 2011")
.col-md-8
%p
%span.light Fingerprint:
%strong= @key.fingerprint
%pre.well-pre
= @key.key
.pull-right
- unless @key.is_a? LDAPKey
= link_to 'Remove', profile_key_path(@key), data: {confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove delete-key"
= render "key_details"
......@@ -15,6 +15,13 @@
Disabled
%p You will not get any notifications via email
.radio
= label_tag nil, class: '' do
= radio_button_tag :notification_level, Notification::N_MENTION, @notification.mention?, class: 'trigger-submit'
.level-title
Mention
%p You will receive notifications only for comments where you was @mentioned
.radio
= label_tag nil, class: '' do
= radio_button_tag :notification_level, Notification::N_PARTICIPATING, @notification.participating?, class: 'trigger-submit'
......
......@@ -52,10 +52,11 @@
- else
%span.light No open milestones available.
&nbsp;
= link_to 'Create new milestone', new_project_milestone_path(issuable.project), target: :blank
- if can? current_user, :admin_milestone, issuable.project
= link_to 'Create new milestone', new_project_milestone_path(issuable.project), target: :blank
.form-group
= f.label :label_ids, class: 'control-label' do
%i.icon-tag
%i.fa.fa-tag
Labels
.col-sm-10
- if issuable.project.labels.any?
......@@ -64,9 +65,15 @@
- else
%span.light No labels yet.
&nbsp;
= link_to 'Create new label', new_project_label_path(issuable.project), target: :blank
- if can? current_user, :admin_label, issuable.project
= link_to 'Create new label', new_project_label_path(issuable.project), target: :blank
.form-actions
- if !issuable.project.empty_repo? && contribution_guide_url(issuable.project) && !issuable.persisted?
%p
Please review the
%strong #{link_to 'guidelines for contribution', contribution_guide_url(issuable.project)}
to this repository.
- if issuable.new_record?
= f.submit "Submit new #{issuable.class.model_name.human.downcase}", class: 'btn btn-create'
- else
......
......@@ -7,5 +7,5 @@
%p= pluralize(commits.count, 'commit')
.col-md-10
%ul.bordered-list
= render commits, project: @project
= render commits, project: project
%hr.lists-separator
......@@ -11,11 +11,9 @@
%ul.breadcrumb.repo-breadcrumb
= commits_breadcrumbs
%li.active
commits
%div{id: dom_id(@project)}
#commits-list= render "commits"
#commits-list= render "commits", project: @project
.clear
= spinner
......
......@@ -4,7 +4,7 @@
.diff-file{id: "diff-#{i}", data: {blob_diff_path: blob_diff_path }}
.diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"}
- if diff_file.deleted_file
%span= diff_file.old_path
%span="#{diff_file.old_path} deleted"
.diff-btn-group
- if @commit.parent_ids.present?
......
%div.issue-form-holder
%h3.page-title= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.iid}"
%hr
- if @repository.exists? && !@repository.empty? && @repository.contribution_guide && !@issue.persisted?
- contribution_guide_url = project_blob_path(@project, tree_join(@repository.root_ref, @repository.contribution_guide.name))
.row
.col-sm-10.col-sm-offset-2
.alert.alert-info
= "Please review the <strong>#{link_to "guidelines for contribution", contribution_guide_url}</strong> to this repository.".html_safe
= form_for [@project, @issue], html: { class: 'form-horizontal issue-form gfm-form' } do |f|
= render 'projects/issuable_form', f: f, issuable: @issue
......
......@@ -9,74 +9,103 @@
%span.pull-right
= link_to 'Change branches', new_project_merge_request_path(@project)
= form_for [@project, @merge_request], html: { class: "merge-request-form gfm-form" } do |f|
.panel.panel-default
.panel-body
.form-group
.light
= f.label :title do
Title *
= f.text_field :title, class: "form-control input-lg js-gfm-input", maxlength: 255, rows: 5, required: true
.form-group
.light
= f.label :description, "Description"
= form_for [@project, @merge_request], html: { class: "merge-request-form form-horizontal gfm-form" } do |f|
.merge-request-form-info
.form-group
= f.label :title, class: 'control-label' do
%strong Title *
.col-sm-10
= f.text_field :title, maxlength: 255, autofocus: true, class: 'form-control pad js-gfm-input', required: true
.form-group.issuable-description
= f.label :description, 'Description', class: 'control-label'
.col-sm-10
= render layout: 'projects/md_preview' do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.clearfix.hint
.pull-left Description is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
.pull-right Attach images (JPG, PNG, GIF) by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control'
.col-sm-12-hint
.pull-left
Parsed with
#{link_to 'Gitlab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
.pull-right
Attach images (JPG, PNG, GIF) by dragging &amp; dropping
or #{link_to 'selecting them', '#', class: 'markdown-selector'}.
.clearfix
.error-alert
.form-group
.issue-assignee
= f.label :assignee_id do
%i.fa.fa-user
Assign to
%div
= project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)
&nbsp;
= link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
.form-group
.issue-milestone
= f.label :milestone_id do
%i.fa.fa-clock-o
Milestone
%div= f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2'})
.form-group
= f.label :label_ids do
%i.fa.fa-tag
Labels
%div
= f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, { selected: @merge_request.label_ids }, multiple: true, class: 'select2'
%hr
.form-group
.issue-assignee
= f.label :assignee_id, class: 'control-label' do
%i.fa.fa-user
Assign to
.col-sm-10
= project_users_select_tag('merge_request[assignee_id]', placeholder: 'Select a user', class: 'custom-form-control', selected: @merge_request.assignee_id, project_id: @merge_request.target_project_id)
&nbsp;
= link_to 'Assign to me', '#', class: 'btn assign-to-me-link'
.form-group
.issue-milestone
= f.label :milestone_id, class: 'control-label' do
%i.fa.fa-clock-o
Milestone
.col-sm-10
- if milestone_options(@merge_request).present?
= f.select(:milestone_id, milestone_options(@merge_request), {include_blank: 'Select milestone'}, {class: 'select2'})
- else
%span.light No open milestones available.
&nbsp;
- if can? current_user, :admin_milestone, @merge_request.target_project
= link_to 'Create new milestone', new_project_milestone_path(@merge_request.target_project), target: :blank
.form-group
= f.label :label_ids, class: 'control-label' do
%i.fa.fa-tag
Labels
.col-sm-10
- if @merge_request.target_project.labels.any?
= f.collection_select :label_ids, @merge_request.target_project.labels.all, :id, :name, {selected: @merge_request.label_ids}, multiple: true, class: 'select2'
- else
%span.light No labels yet.
&nbsp;
- if can? current_user, :admin_label, @merge_request.target_project
= link_to 'Create new label', new_project_label_path(@merge_request.target_project), target: :blank
.panel-footer
.form-actions
- if contribution_guide_url(@target_project)
%p
Please review the
%strong #{link_to "guidelines for contribution", contribution_guide_url(@target_project)}
%strong #{link_to 'guidelines for contribution', contribution_guide_url(@target_project)}
to this repository.
= f.hidden_field :source_project_id
= f.hidden_field :source_branch
= f.hidden_field :target_project_id
= f.hidden_field :target_branch
= f.hidden_field :source_branch
= f.submit 'Submit merge request', class: "btn btn-create"
= f.submit 'Submit merge request', class: 'btn btn-create'
.mr-compare
= render "projects/commits/commit_list"
%h4 Changes
- if @diffs.present?
= render "projects/diffs/diffs", diffs: @diffs, project: @project
- elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
.bs-callout.bs-callout-danger
%h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
%p To preserve performance the line changes are not shown.
- else
.bs-callout.bs-callout-danger
%h4 This comparison includes huge diff.
%p To preserve performance the line changes are not shown.
.mr-compare.merge-request
%ul.nav.nav-tabs.merge-request-tabs
%li.commits-tab{data: {action: 'commits'}}
= link_to url_for(params) do
%i.fa.fa-history
Commits
%span.badge= @commits.size
%li.diffs-tab{data: {action: 'diffs'}}
= link_to url_for(params) do
%i.fa.fa-list-alt
Changes
%span.badge= @diffs.size
.commits.tab-content
= render "projects/commits/commits", project: @project
.diffs.tab-content
- if @diffs.present?
= render "projects/diffs/diffs", diffs: @diffs, project: @project
- elsif @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
.bs-callout.bs-callout-danger
%h4 This comparison includes more than #{MergeRequestDiff::COMMITS_SAFE_SIZE} commits.
%p To preserve performance the line changes are not shown.
- else
.bs-callout.bs-callout-danger
%h4 This comparison includes a huge diff.
%p To preserve performance the line changes are not shown.
:javascript
$('.assign-to-me-link').on('click', function(e){
......@@ -85,3 +114,9 @@
});
window.project_image_path_upload = "#{upload_image_project_path @project}";
:javascript
var merge_request
merge_request = new MergeRequest({
action: 'commits'
});
......@@ -42,7 +42,7 @@
%span.badge= @merge_request.mr_and_commit_notes.count
%li.commits-tab{data: {action: 'commits'}}
= link_to project_merge_request_path(@project, @merge_request), title: 'Commits' do
%i.fa.fa-database
%i.fa.fa-history
Commits
%span.badge= @commits.size
%li.diffs-tab{data: {action: 'diffs'}}
......
- if @commits.present?
.panel.panel-default
.panel-heading
%i.fa.fa-list
Commits (#{@commits.count})
.commits.mr-commits
- if @commits.count > 8
%ul.first-commits.well-list
- @commits.first(8).each do |commit|
= render "projects/commits/commit", commit: commit, project: @merge_request.source_project
%li.bottom
8 of #{@commits.count} commits displayed.
%strong
%a.show-all-commits Click here to show all
- if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
%ul.all-commits.hide.well-list
- @commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE).each do |commit|
= render "projects/commits/inline_commit", commit: commit, project: @merge_request.source_project
%li
other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues.
- else
%ul.all-commits.hide.well-list
- @commits.each do |commit|
= render "projects/commits/inline_commit", commit: commit, project: @merge_request.source_project
- else
%ul.well-list
- @commits.each do |commit|
= render "projects/commits/commit", commit: commit, project: @merge_request.source_project
= render "projects/commits/commits", project: @merge_request.source_project
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.
File mode changed from 100755 to 100644
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