Commit 2df9a760 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into 6_5_ce

Signed-off-by: default avatarDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>

Conflicts:
	CHANGELOG
	VERSION
	app/assets/stylesheets/generic/common.scss
	app/views/projects/edit.html.haml
	config.ru
	db/schema.rb
	doc/install/installation.md
	doc/update/6.0-to-6.1.md
	doc/update/6.1-to-6.2.md
	lib/gitlab/upgrader.rb
parents 4dd2c896 a68630e0
v 6.5.0
- Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard)
- Add color custimization and previewing to broadcast messages
- Fixed notes anchors
- Load new comments in issues dynamically
- Added sort options to Public page
- New filters (assigned/authored/all) for Dashboard#issues/merge_requests (sponsored by Say Media)
- Add project visibility icons to dashboard
- Enable secure cookies if https used
- Protect users/confirmation with rack_attack
- Default HTTP headers to protect against MIME-sniffing, force https if enabled
- Bootstrap 3 with responsive UI
- New repository download formats: tar.bz2, zip, tar (Jason Hollingsworth)
- Restyled accept widgets for MR
- SCSS refactored
- Use jquery timeago plugin
- Fix 500 error for rdoc files
- Ability to customize merge commit message (sponsored by Say Media)
- Search autocomplete via ajax
- Add website url to user profile
- Files API supports base64 encoded content (sponsored by O'Reilly Media)
- Added support for Go's repository retrieval (Bruno Albuquerque)
v6.4.3
- Don't use unicorn worker killer if PhusionPassenger is defined
v6.4.2
- Fixed wrong behaviour of script/upgrade.rb
......
This diff is collapsed.
......@@ -30,7 +30,7 @@ gem 'omniauth-github'
# Extracting information from a git repository
# Provide access to Gitlab::Git library
gem "gitlab_git", "~> 4.0.0.pre"
gem "gitlab_git", "~> 4.0.0"
# Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
......@@ -53,6 +53,9 @@ gem "grape", "~> 0.6.1"
gem "grape-entity", "~> 0.3.0"
gem 'rack-cors', require: 'rack/cors'
# Email validation
gem "email_validator", "~> 1.4.0", :require => 'email_validator/strict'
# Format dates and times
# based on human-friendly examples
gem "stamp"
......@@ -61,7 +64,7 @@ gem "stamp"
gem 'enumerize'
# Pagination
gem "kaminari", "~> 0.14.1"
gem "kaminari", "~> 0.15.1"
# HAML
gem "haml-rails"
......@@ -80,7 +83,7 @@ gem "seed-fu"
# Markdown to HTML
gem "redcarpet", "~> 2.2.2"
gem "github-markup", "~> 0.7.4", require: 'github/markup'
gem "github-markup", "~> 0.7.4", require: 'github/markup', git: 'https://github.com/gitlabhq/markup.git', ref: '61ade389c1e1c159359338f570d18464a44ddbc4'
# Asciidoc to HTML
gem "asciidoctor"
......@@ -121,7 +124,7 @@ gem "redis-rails"
gem 'tinder', '~> 1.9.2'
# HipChat integration
gem "hipchat", "~> 0.9.0"
gem "hipchat", "~> 0.14.0"
# Flowdock integration
gem "gitlab-flowdock-git-hook", "~> 0.4.2"
......@@ -145,17 +148,16 @@ gem "therubyracer"
gem 'turbolinks'
gem 'jquery-turbolinks'
gem 'chosen-rails', "1.0.1"
gem 'select2-rails'
gem 'jquery-atwho-rails', "~> 0.3.3"
gem "jquery-rails", "2.1.3"
gem "jquery-ui-rails", "2.0.2"
gem "modernizr", "2.6.2"
gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 2.3'
gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2'
gem "gemoji", "~> 1.3.0"
gem "gon", git: "https://github.com/gitlabhq/gon.git", ref: '58ca8e17273051cb370182cabd3602d1da6783ab'
gem "gon", '~> 5.0.0'
group :development do
gem "annotate", "~> 2.6.0.beta2"
......
GIT
remote: https://github.com/gitlabhq/gon.git
revision: 58ca8e17273051cb370182cabd3602d1da6783ab
ref: 58ca8e17273051cb370182cabd3602d1da6783ab
remote: https://github.com/gitlabhq/markup.git
revision: 61ade389c1e1c159359338f570d18464a44ddbc4
ref: 61ade389c1e1c159359338f570d18464a44ddbc4
specs:
gon (4.1.1)
actionpack (>= 2.3.0)
json
github-markup (0.7.6)
GEM
remote: https://rubygems.org/
......@@ -57,7 +55,7 @@ GEM
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootstrap-sass (2.3.2.2)
bootstrap-sass (3.0.3.0)
sass (~> 3.2)
builder (3.1.4)
capybara (2.1.0)
......@@ -73,12 +71,6 @@ GEM
celluloid (0.15.2)
timers (~> 1.1.0)
charlock_holmes (0.6.9.4)
chosen-rails (1.0.1)
coffee-rails (>= 3.2)
compass-rails (>= 1.0)
railties (>= 3.0)
sass-rails (>= 3.2)
chunky_png (1.2.9)
cliver (0.2.2)
code_analyzer (0.4.3)
sexp_processor
......@@ -94,12 +86,6 @@ GEM
coffee-script-source (1.6.3)
colored (1.2)
colorize (0.5.8)
compass (0.12.2)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.1)
compass-rails (1.1.1)
compass (>= 0.12.2)
connection_pool (1.2.0)
coveralls (0.7.0)
multi_json (~> 1.3)
......@@ -128,6 +114,8 @@ GEM
email_spec (1.5.0)
launchy (~> 2.1)
mail (~> 2.2)
email_validator (1.4.0)
activemodel
enumerize (0.7.0)
activesupport (>= 3.2)
equalizer (0.0.8)
......@@ -163,12 +151,10 @@ GEM
dotenv (>= 0.7)
thor (>= 0.13.6)
formatador (0.2.4)
fssm (0.2.10)
gemoji (1.3.1)
gherkin-ruby (0.3.1)
racc
github-markdown (0.5.5)
github-markup (0.7.5)
gitlab-flowdock-git-hook (0.4.2.2)
gitlab-grit (>= 2.4.1)
multi_json
......@@ -195,7 +181,7 @@ GEM
gitlab-pygments.rb (0.5.4)
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
gitlab_git (4.0.0.pre)
gitlab_git (4.0.0)
activesupport (~> 4.0.0)
gitlab-grit (~> 2.6.1)
gitlab-linguist (~> 2.9.5)
......@@ -206,6 +192,9 @@ GEM
omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1)
gon (5.0.1)
actionpack (>= 2.3.0)
json
grape (0.6.1)
activesupport
builder
......@@ -241,7 +230,7 @@ GEM
railties (~> 4.0.0)
hashie (2.0.5)
hike (1.2.3)
hipchat (0.9.0)
hipchat (0.14.0)
httparty
httparty
http_parser.rb (0.5.3)
......@@ -270,7 +259,7 @@ GEM
json (1.8.1)
jwt (0.1.8)
multi_json (>= 1.5)
kaminari (0.14.1)
kaminari (0.15.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.8.1)
......@@ -292,7 +281,7 @@ GEM
minitest (4.7.5)
modernizr (2.6.2)
sprockets (~> 2.0)
multi_json (1.8.2)
multi_json (1.8.4)
multi_xml (0.5.5)
multipart-post (1.2.0)
mysql2 (0.3.11)
......@@ -569,10 +558,9 @@ DEPENDENCIES
awesome_print
better_errors
binding_of_caller
bootstrap-sass (~> 2.3)
bootstrap-sass (~> 3.0)
capybara
carrierwave
chosen-rails (= 1.0.1)
coffee-rails
colored
coveralls
......@@ -581,6 +569,7 @@ DEPENDENCIES
devise (= 3.0.4)
devise-async (= 0.8.0)
email_spec
email_validator (~> 1.4.0)
enumerize
factory_girl_rails
ffaker
......@@ -588,30 +577,30 @@ DEPENDENCIES
font-awesome-rails (~> 3.2)
foreman
gemoji (~> 1.3.0)
github-markup (~> 0.7.4)
github-markup (~> 0.7.4)!
gitlab-flowdock-git-hook (~> 0.4.2)
gitlab-gollum-lib (~> 1.0.2)
gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 2.9.6)
gitlab-pygments.rb (~> 0.5.4)
gitlab_git (~> 4.0.0.pre)
gitlab_git (~> 4.0.0)
gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.3)
gon!
gon (~> 5.0.0)
grape (~> 0.6.1)
grape-entity (~> 0.3.0)
growl
guard-rspec
guard-spinach
haml-rails
hipchat (~> 0.9.0)
hipchat (~> 0.14.0)
httparty
jasmine (= 2.0.0.rc5)
jquery-atwho-rails (~> 0.3.3)
jquery-rails (= 2.1.3)
jquery-turbolinks
jquery-ui-rails (= 2.0.2)
kaminari (~> 0.14.1)
kaminari (~> 0.15.1)
launchy
letter_opener
minitest (~> 4.7.0)
......
This diff is collapsed.
## GitLab: self hosted Git management software
![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png)
![logo](https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/gitlab_logo.png)
![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif)
......@@ -34,7 +34,7 @@
* [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users).
* [GitLab CI](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
* [GitLab CI](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
### Requirements
......@@ -62,7 +62,7 @@
#### Unofficial installation methods
* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
* [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
* [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems.
......@@ -145,13 +145,13 @@ or start each component separately
* [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
* [Contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) describes how to submit merge requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
* [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
* [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations.
* [#gitlab IRC channel](http://www.freenode.net/) on Freenode to get in touch with other GitLab users and get help, it's managed by James Newton, Drew Blessing and Sam Gleske
* [#gitlab IRC channel](http://www.freenode.net/) on Freenode to get in touch with other GitLab users and get help, it's managed by James Newton (newton), Drew Blessing (dblessing), and Sam Gleske (sag47).
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
......
......@@ -8,6 +8,23 @@ class Admin
else
elems.removeAttr 'disabled'
$('body').on 'click', '.js-toggle-colors-link', (e) ->
e.preventDefault()
$('.js-toggle-colors-link').hide()
$('.js-toggle-colors-container').show()
$('input#broadcast_message_color').on 'input', ->
previewColor = $('input#broadcast_message_color').val()
$('div.broadcast-message-preview').css('background-color', previewColor)
$('input#broadcast_message_font').on 'input', ->
previewColor = $('input#broadcast_message_font').val()
$('div.broadcast-message-preview').css('color', previewColor)
$('textarea#broadcast_message_message').on 'input', ->
previewMessage = $('textarea#broadcast_message_message').val()
$('div.broadcast-message-preview span').text(previewMessage)
$('.log-tabs a').click (e) ->
e.preventDefault()
$(this).tab('show')
......
......@@ -19,7 +19,6 @@
//= require jquery.turbolinks
//= require bootstrap
//= require modernizr
//= require chosen-jquery
//= require select2
//= require raphael
//= require g.raphael-min
......
......@@ -194,11 +194,14 @@ class BranchGraph
fill: @colors[commit.space]
stroke: "none"
)
r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr(
fill: "url(#{commit.author.icon})"
avatar_box_x = @offsetX + @unitSpace * @mspace + 10
avatar_box_y = y - 10
r.rect(avatar_box_x, avatar_box_y, 20, 20).attr(
stroke: @colors[commit.space]
"stroke-width": 2
)
r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
"text-anchor": "start"
font: "14px Monaco, monospace"
......
......@@ -47,5 +47,9 @@ class Dispatcher
initSearch: ->
autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts')
new SearchAutocomplete(autocomplete_json)
opts = $('.search-autocomplete-opts')
path = opts.data('autocomplete-path')
project_id = opts.data('autocomplete-project-id')
project_ref = opts.data('autocomplete-project-ref')
new SearchAutocomplete(path, project_id, project_ref)
......@@ -29,12 +29,10 @@
$('#filter_issue_search').val($('#issue_search').val())
initSelects: ->
$("#update_status").chosen()
$("#update_assignee_id").chosen()
$("#update_milestone_id").chosen()
$("#label_name").chosen()
$("#assignee_id").chosen()
$("#milestone_id").chosen()
$("select#update_status").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#update_assignee_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#update_milestone_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("select#label_name").select2(width: 'resolve', dropdownAutoWidth: true)
$("#milestone_id, #assignee_id, #label_name").on "change", ->
$(this).closest("form").submit()
......@@ -79,3 +77,9 @@
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-filters").show()
$ ->
$('.edit-issue.inline-update input[type="submit"]').hide();
$("body").on "change", ".edit-issue.inline-update select", ->
$(this).submit()
......@@ -67,8 +67,8 @@ $ ->
$('.appear-data').fadeIn()
e.preventDefault()
# Initialize chosen selects
$('select.chosen').chosen()
# Initialize select2 selects
$('select.select2').select2(width: 'resolve', dropdownAutoWidth: true)
# Initialize tooltips
$('.has_tooltip').tooltip()
......@@ -81,6 +81,7 @@ $ ->
$(@).parents('form').submit()
$("abbr.timeago").timeago()
$('.js-timeago').timeago()
# Flash
if (flash = $(".flash-container")).length > 0
......@@ -125,12 +126,6 @@ $ ->
$(@).remove()
(($) ->
_chosen = $.fn.chosen
$.fn.extend chosen: (options) ->
default_options = search_contains: "true"
$.extend default_options, options
_chosen.apply @, [default_options]
# Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: ->
$(@).attr('disabled', 'disabled').addClass('disabled')
......
......@@ -2,8 +2,8 @@
# * Filter merge requests
#
@merge_requestsPage = ->
$('#assignee_id').chosen()
$('#milestone_id').chosen()
$('#assignee_id').select2()
$('#milestone_id').select2()
$('#milestone_id, #assignee_id').on 'change', ->
$(this).closest('form').submit()
......@@ -24,6 +24,8 @@ class MergeRequest
modal = $('#modal_merge_info').modal(show: false)
disableButtonIfEmptyField '#merge_commit_message', '.accept_merge_request'
# Local jQuery finder
$: (selector) ->
this.$el.find(selector)
......
This diff is collapsed.
This diff is collapsed.
class NotesVotes
updateVotes: ->
votes = $("#votes .votes")
notes = $("#notes-list .note .vote")
# only update if there is a vote display
if votes.size()
upvotes = notes.filter(".upvote").size()
downvotes = notes.filter(".downvote").size()
votesCount = upvotes + downvotes
upvotesPercent = (if votesCount then (100.0 / votesCount * upvotes) else 0)
downvotesPercent = (if votesCount then (100.0 - upvotesPercent) else 0)
# change vote bar lengths
votes.find(".bar-success").css "width", upvotesPercent + "%"
votes.find(".bar-danger").css "width", downvotesPercent + "%"
# replace vote numbers
votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
@NotesVotes = NotesVotes
......@@ -35,7 +35,7 @@ $ ->
$('a, button', scope).removeClass 'active'
$(@).addClass 'active'
$('#project_clone', scope).val $(@).data 'clone'
$(".clone").text("").append 'git remote add origin ' + $(@).data 'clone'
$(".clone").text("").append $(@).data 'clone'
# Ref switcher
$('.project-refs-select').on 'change', ->
......
class SearchAutocomplete
constructor: (json) ->
constructor: (search_autocomplete_path, project_id, project_ref) ->
project_id = '' unless project_id
project_ref = '' unless project_ref
query = "?project_id=" + project_id + "&project_ref=" + project_ref
$("#search").autocomplete
source: json
source: search_autocomplete_path + query
minLength: 1
select: (event, ui) ->
location.href = ui.item.url
......
......@@ -46,11 +46,7 @@ class window.ContributorsGraph
class window.ContributorsMasterGraph extends ContributorsGraph
constructor: (@data) ->
if $(window).width() > 1214
@width = 1100
else
@width = 870
@width = $('.container').width() - 70
@height = 200
@x = null
@y = null
......@@ -88,7 +84,6 @@ class window.ContributorsMasterGraph extends ContributorsGraph
x(d.date)
).y0(@height).y1((d) ->
xa = d.commits = d.commits ? d.additions ? d.deletions
console.log(xa)
y(xa)
).interpolate("basis")
create_brush: ->
......@@ -124,11 +119,7 @@ class window.ContributorsMasterGraph extends ContributorsGraph
class window.ContributorsAuthorGraph extends ContributorsGraph
constructor: (@data) ->
if $(window).width() > 1214
@width = 490
else
@width = 380
@width = $('.container').width()/2 - 100
@height = 200
@x = null
@y = null
......
......@@ -6,12 +6,12 @@ $ ->
avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24')
markup = "<div class='user-result'>"
markup += "<div class='user-image'><img class='avatar s24' src='" + avatar + "'></div>"
markup += "<div class='user-name'>" + user.name + "</div>"
markup += "<div class='user-username'>" + user.username + "</div>"
markup += "</div>"
markup
"<div class='user-result'>
<div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
<div class='user-name'>#{user.name}</div>
<div class='user-username'>#{user.username}</div>
</div>"
userFormatSelection = (user) ->
user.name
......
......@@ -4,19 +4,44 @@
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.gitlab
*= require jquery.atwho
*= require chosen
*= require select2
*= require_self
*/
@import "main/variables.scss";
@import "main/mixins.scss";
@import "main/fonts.scss";
@import "main/layout.scss";
/**
* Customized Twitter bootstrap
*/
@import 'gl_bootstrap';
/**
* GitLab bootstrap:
* Font icons
*
*/
@import "gitlab_bootstrap.scss";
@import "font-awesome";
@import "common.scss";
@import "selects.scss";
/**
* Generic css (forms, nav etc):
*/
@import "generic/avatar.scss";
@import "generic/common.scss";
@import "generic/typography.scss";
@import "generic/buttons.scss";
@import "generic/blocks.scss";
@import "generic/ui_box.scss";
@import "generic/issue_box.scss";
@import "generic/files.scss";
@import "generic/lists.scss";
@import "generic/forms.scss";
@import "generic/selects.scss";
/**
* Page specific styles (issues, projects etc):
*/
@import "sections/header.scss";
@import "sections/nav.scss";
@import "sections/commits.scss";
......@@ -39,6 +64,9 @@
@import "sections/dashboard.scss";
@import "sections/stat_graph.scss";
/**
* Code ighlight
*/
@import "highlight/white.scss";
@import "highlight/dark.scss";
@import "highlight/solarized_dark.scss";
......@@ -57,4 +85,3 @@
* Styles for JS behaviors.
*/
@import "behaviors.scss";
.light-well {
background: #f9f9f9;
padding: 15px;
}
......@@ -143,16 +143,27 @@
line-height: 16px;
margin: 2px;
}
}
.btn-block {
width: 100%;
margin: 0;
margin-bottom: 15px;
&.btn {
padding: 6px 0;
}
}
.btn,
.btn-group {
&.grouped {
margin-right: 7px;
float: left;
&:last-child {
margin-right: 0px;
}
&.btn-block {
width: 100%;
margin: 0;
padding: 6px 0;
margin-bottom: 15px;
}
}
.btn-group-small > .btn { @extend .btn.btn-small; }
.btn-group-tiny > .btn { @extend .btn.btn-tiny; }
html {
overflow-y: scroll;
/** COLORS **/
.cgray { color: gray }
.clgray { color: #BBB }
.cred { color: #D12F19 }
.cgreen { color: #4a2 }
.cblue { color: #29A }
.cblack { color: #111 }
.cdark { color: #444 }
.camber { color: #ffc000 }
.cwhite { color: #fff!important }
.bgred { background: #F2DEDE!important }
/** COMMON CLASSES **/
.left { float:left }
.prepend-top-10 { margin-top:10px }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-20 { margin-left:20px }
.append-right-10 { margin-right:10px }
.append-right-20 { margin-right:20px }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-15 { margin-bottom:15px }
.append-bottom-20 { margin-bottom:20px }
.inline { display: inline-block }
.padded { padding:20px }
.ipadded { padding:20px!important }
.lborder { border-left:1px solid #eee }
.underlined_link { text-decoration: underline; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
.tiny { font-weight: normal }
.vtop { vertical-align: top !important; }
/** ALERT MESSAGES **/
.alert.alert-disabled {
background: #EEE;
color: #777;
border-color: #DDD;
}
/** HELPERS **/
.nothing_here_message {
text-align: center;
padding: 20px;
color: #666;
font-weight: normal;
font-size: 16px;
line-height: 36px;
}
/** LAYOUT **/
body {
-webkit-font-smoothing: antialiased;
margin-bottom: 20px;
.slead {
color: #666;
font-size: 14px;
margin-bottom: 12px;
font-weight: normal;
line-height: 24px;
}
.container {
padding-top: 0;
z-index: 5;
.tab-content {
overflow: visible;
}
.container .content {
margin: 0 0;
@media (max-width: 1200px) {
.only-wide {
display: none;
}
}
.author_link {
color: $link_color;
pre.well-pre {
border: 1px solid #EEE;
background: #f9f9f9;
border-radius: 0;
color: #555;
}
.help li { color:$style_color; }
.input-append .btn.active, .input-prepend .btn.active {
background: #CCC;
border-color: #BBB;
text-shadow: 0 1px 1px #fff;
font-weight: bold;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
.back-link {
/** Big Labels **/
.state-label {
font-size: 14px;
padding: 6px 25px;
text-align: center;
@include border-radius(4px);
text-shadow: none;
margin-left: 10px;
&.state-label-green {
background: #4A4;
color: #FFF;
}
&.state-label-red {
background: #DA4E49;
color: #FFF;
}
}
table a code {
position: relative;
top: -2px;
margin-right: 3px;
.dropdown-menu > li > a {
text-shadow: none;
}
.loading {
margin: 20px auto;
background: url(ajax_loader.gif) no-repeat center center;
width: 40px;
height: 40px;
&.loading-gray {
background: url(ajax_loader_gray.gif) no-repeat center center;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background: #29b;
}
.breadcrumb > li + li:before {
content: "/";
padding: 0;
color: #666;
}
.str-truncated {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: 82%;
}
/** FLASH message **/
......@@ -70,6 +155,31 @@ table a code {
padding: 10px;
}
}
.author_link {
color: $link_color;
}
.help li { color:$style_color; }
.back-link {
font-size: 14px;
}
table a code {
position: relative;
top: -2px;
margin-right: 3px;
}
.loading {
margin: 20px auto;
background: url(ajax_loader.gif) no-repeat center center;
width: 40px;
height: 40px;
&.loading-gray {
background: url(ajax_loader_gray.gif) no-repeat center center;
}
}
span.update-author {
display: block;
......@@ -91,19 +201,6 @@ span.update-author {
display: inline;
}
ul.breadcrumb {
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
font-size: 16px;
}
}
.line_holder {
&:hover {
td {
......@@ -118,18 +215,6 @@ p.time {
margin: 30px 3px 3px 2px;
}
.search-holder {
label, input {
height: 30px;
padding: 0;
font-size: 14px;
}
label {
line-height: 30px;
color: #666;
}
}
.highlight {
text-shadow: none;
}
......@@ -208,7 +293,7 @@ li.note {
}
.git_error_tips {
@extend .span6;
@extend .col-md-6;
text-align: left;
margin-top: 40px;
pre {
......@@ -235,6 +320,7 @@ li.note {
background: #C67;
margin: 0;
color: #FFF;
margin-top: -1px;
text-align: center;
a {
......@@ -352,12 +438,6 @@ table {
min-height: 100px;
}
.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
@extend .btn-new;
padding: 5px 15px;
text-shadow: none;
}
.broadcast-message {
padding: 10px;
text-align: center;
......@@ -365,6 +445,11 @@ table {
color: #BBB;
}
.broadcast-message-preview {
@extend .broadcast-message;
margin-bottom: 20px;
}
.ajax-users-select {
width: 400px;
......@@ -398,3 +483,14 @@ table {
font-weight: bolder;
}
}
.btn-sign-in {
margin-top: 7px;
text-shadow: none;
}
.side-filters {
fieldset {
margin-bottom: 15px;
}
}
......@@ -20,7 +20,6 @@
text-align: left;
color: $style_color;
padding: 9px 10px;
height: 18px;
.options {
float: right;
......@@ -46,7 +45,7 @@
text-align: center;
img {
padding: 100px;
max-width: 300px;
max-width: 50%;
}
}
......
form {
@extend .form-horizontal;
label {
@extend .control-label;
&.radio-label {
text-align: left;
width: 100%;
margin-left: 0;
input[type="radio"] {
margin-top: 1px !important;
}
}
&.list-label {
float: none;
padding: 0 !important;
margin: 0;
text-align: left;
}
}
}
input.input-xpadding,
.add-on.input-xpadding {
padding: 6px 10px;
}
.control-group {
.control-label {
padding-top: 6px;
}
.controls {
input, textarea {
padding: 6px 10px;
}
input[type="radio"], input[type="checkbox"] {
margin-top: 6px;
}
.add-on {
padding: 6px;
}
}
}
input[type='search'].search-text-input {
background-image: url("icon-search.png");
background-repeat: no-repeat;
background-position: 10px;
padding-left: 25px;
@include border-radius(4px);
border: 1px solid #ccc;
}
input[type='text'].danger {
......@@ -64,7 +13,6 @@ input[type='text'].danger {
fieldset legend {
font-size: 16px;
margin-bottom: 10px;
}
.datetime-controls {
......@@ -72,3 +20,34 @@ fieldset legend {
width: 100px;
}
}
.form-actions {
padding: 17px 20px 18px;
margin-top: 18px;
margin-bottom: 18px;
background-color: whitesmoke;
border-top: 1px solid #e5e5e5;
padding-left: 17%;
}
label {
&.control-label {
@extend .col-sm-2;
}
&.inline-label {
margin: 0;
}
}
.inline-input-group {
width: 250px;
}
.input-mx-250 {
max-width: 250px;
}
.input-mn-300 {
min-width: 300px;
}
/**
* Issue box:
* Huge block (one per page) for storing title, descripion and other information.
* Used for Issue#show page, MergeRequest#show page etc
*
* CLasses:
* .issue-box - Regular box
*/
.issue-box {
color: #666;
margin:20px 0;
background: #FAFAFA;
border: 1px solid #DDD;
.control-group {
margin-bottom: 0;
}
.title {
font-size: 20px;
font-weight: 500;
line-height: 28px;
margin: 0;
color: #444;
}
.context {
border: none;
background-color: #f5f5f5;
border: none;
border-top: 1px solid #eee;
}
.description {
border-top: 1px solid #eee;
}
.title, .context, .description {
padding: 15px;
.clearfix {
margin: 0;
}
}
}
......@@ -4,7 +4,9 @@
*/
.well-list {
margin: 0;
padding: 0;
list-style: none;
li {
padding: 10px;
min-height: 20px;
......
/** Select2 selectbox style override **/
.select2-container, .select2-container.select2-drop-above {
.select2-choice {
background: #FFF;
border-color: #BBB;
.select2-arrow {
background: #FFF;
}
}
}
.select2-drop-active {
border: 1px solid #BBB;
margin-top: 4px;
.select2-search input {
background: #fafafa;
border-color: #DDD;
}
.select2-results {
max-height: 350px;
.select2-highlighted {
background: $bg_style_color;
}
}
}
select {
&.select2 {
width: 100px;
}
&.select2-sm {
width: 100px;
}
}
@media (min-width: $screen-sm-min) {
select {
&.select2 {
width: 150px;
}
&.select2-sm {
width: 120px;
}
}
}
/* Medium devices (desktops, 992px and up) */
@media (min-width: $screen-md-min) {
select {
&.select2 {
width: 170px;
}
&.select2-sm {
width: 140px;
}
}
}
/* Large devices (large desktops, 1200px and up) */
@media (min-width: $screen-lg-min) {
select {
&.select2 {
width: 200px;
}
&.select2-sm {
width: 150px;
}
}
}
/** Branch/tag selector **/
.project-refs-form .select2-container {
margin-right: 10px;
}
......@@ -2,11 +2,6 @@
* Headers
*
*/
h1, h2, h3, h4, h5, h6 {
font-weight: 500;
line-height: 1.1;
}
h1.page-title {
@include page-title;
font-size: 28px;
......@@ -99,6 +94,7 @@ a:focus {
background: #f5f5f5;
}
ul {
padding: 0;
margin: 0 0 9px 25px !important;
}
}
......
/**
* ===================================
* Contain UI block elements:
* UI box:
* Block element for separating information on page.
* Used for storing issues lists, grouped data.
* You can have multiple ui boxes on one page
*
* Classes:
* .ui-box - for any block & widgets
* ===================================
*/
/**
* UI Block
* .ui-box.ui-box-small - same but with smaller title
* .ui-box.ui-box-danger - with red title
*
* Ex. 1: List
* .ui-box
* .title
* # title here
* %ul
* # content here
*
* Ex. 2: Block data
* .ui-box
* .title
* # title here
* .body
* # content here
*
*/
.ui-box {
background: #FFF;
margin-bottom: 20px;
border: 1px solid #DDD;
word-wrap: break-word;
&.small-box {
margin-bottom: 10px;
.title {
font-size: 13px;
line-height: 30px;
a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
}
&.ui-box-show {
color: #666;
margin:20px 0;
background: #FAFAFA;
.control-group {
margin-bottom: 0;
}
}
&.ui-box-danger {
background: #f7f7f7;
border: none;
.title {
background: #D65;
color: #fff;
text-shadow: 0 1px 1px #900;
}
img {
max-width: 100%;
}
img { max-width: 100%; }
pre {
code {
background: none !important;
}
}
.ui-box-head,
.ui-box-body,
.ui-box-bottom {
padding: 15px;
.clearfix {
margin: 0;
}
}
.ui-box-head {
.box-title {
font-size: 20px;
font-weight: 500;
line-height: 28px;
margin: 0;
color: #444;
}
h3 {
margin: 0;
}
}
.ui-box-body {
border: none;
background-color: #f5f5f5;
border: none;
border-top: 1px solid #eee;
}
.ui-box-bottom {
border-top: 1px solid #eee;
}
ul {
margin: 0;
padding: 0;
}
.title {
......@@ -146,6 +94,10 @@
}
}
.body {
padding: 10px;
}
&.padded {
h5, .title {
margin: -20px;
......@@ -177,13 +129,45 @@
}
}
/*
* Small box
*/
.ui-box.ui-box-small {
margin-bottom: 10px;
.title {
font-size: 13px;
line-height: 30px;
a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
}
/*
* Danger box
*/
.ui-box.ui-box-danger {
background: #f7f7f7;
border: none;
.title {
background: #D65;
color: #fff;
text-shadow: none;
font-weight: 500;
}
}
/*
* Block under tw-bootstrap tabs
*/
.tab-pane {
.ui-box {
margin: 3px 3px 25px 3px;
}
}
.light-well {
background: #f9f9f9;
padding: 15px;
}
/** Override bootstrap variables **/
$baseFontSize: 13px !default;
$baseLineHeight: 18px !default;
/**
* BOOTSTRAP
*/
@import "bootstrap/variables";
@import "bootstrap/mixins";
@import "bootstrap/reset";
@import "bootstrap/scaffolding";
@import "bootstrap/grid";
@import "bootstrap/layouts";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/forms";
@import "bootstrap/tables";
@import "bootstrap/sprites";
@import "bootstrap/dropdowns";
@import "bootstrap/wells";
@import "bootstrap/component-animations";
@import "bootstrap/close";
@import "bootstrap/button-groups";
@import "bootstrap/alerts";
@import "bootstrap/navs";
@import "bootstrap/navbar";
@import "bootstrap/breadcrumbs";
@import "bootstrap/pagination";
@import "bootstrap/pager";
@import "bootstrap/modals";
@import "bootstrap/tooltip";
@import "bootstrap/popovers";
@import "bootstrap/thumbnails";
@import "bootstrap/media";
@import "bootstrap/labels-badges";
@import "bootstrap/progress-bars";
@import "bootstrap/accordion";
@import "bootstrap/carousel";
@import "bootstrap/hero-unit";
@import "bootstrap/utilities";
@import "bootstrap/responsive-utilities";
@import "bootstrap/responsive-1200px-min";
/**
* Font icons
*
*/
@import "font-awesome";
/**
* GitLab bootstrap.
* Overrides some styles of twitter bootstrap.
* Also give some common classes for GitLab app
*/
@import "gitlab_bootstrap/variables.scss";
@import "gitlab_bootstrap/fonts.scss";
@import "gitlab_bootstrap/mixins.scss";
@import "gitlab_bootstrap/avatar.scss";
@import "gitlab_bootstrap/nav.scss";
@import "gitlab_bootstrap/common.scss";
@import "gitlab_bootstrap/typography.scss";
@import "gitlab_bootstrap/buttons.scss";
@import "gitlab_bootstrap/blocks.scss";
@import "gitlab_bootstrap/files.scss";
@import "gitlab_bootstrap/lists.scss";
@import "gitlab_bootstrap/forms.scss";
/** COLORS **/
.cgray { color: gray }
.clgray { color: #BBB }
.cred { color: #D12F19 }
.cgreen { color: #4a2 }
.cblue { color: #29A }
.cblack { color: #111 }
.cdark { color: #444 }
.camber { color: #ffc000 }
.cwhite { color: #fff!important }
.bgred { background: #F2DEDE!important }
/** COMMON CLASSES **/
.left { float:left }
.prepend-top-10 { margin-top:10px }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-20 { margin-left:20px }
.append-right-10 { margin-right:10px }
.append-right-20 { margin-right:20px }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-20 { margin-bottom:20px }
.inline { display: inline-block }
.padded { padding:20px }
.ipadded { padding:20px!important }
.lborder { border-left:1px solid #eee }
.underlined_link { text-decoration: underline; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
.tiny { font-weight: normal }
.vtop { vertical-align: top !important; }
/** ALERT MESSAGES **/
.alert.alert-disabled {
background: #EEE;
color: #777;
border-color: #DDD;
}
/** HELPERS **/
.nothing_here_message {
text-align: center;
padding: 20px;
color: #666;
font-weight: normal;
font-size: 16px;
line-height: 36px;
}
.slead {
color: #666;
font-size: 14px;
margin-bottom: 12px;
font-weight: normal;
line-height: 24px;
}
.tab-content {
overflow: visible;
}
@media (max-width: 1200px) {
.only-wide {
display: none;
}
}
.pagination ul > li > a, .pagination ul > li >span {
@include linear-gradient(#f1f1f1, #e1e1e1);
color: #333;
text-shadow: 0 1px 1px #FFF;
}
pre.well-pre {
border: 1px solid #EEE;
background: #f9f9f9;
border-radius: 0;
color: #555;
}
.input-append .btn.active, .input-prepend .btn.active {
background: #CCC;
border-color: #BBB;
text-shadow: 0 1px 1px #fff;
font-weight: bold;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
.label {
padding: 2px 4px;
font-size: 12px;
font-style: normal;
font-weight: normal;
&.label-gray {
background-color: #eee;
color: #999;
text-shadow: none;
}
}
/** Big Labels **/
.state-label {
font-size: 14px;
padding: 5px 15px;
text-align: center;
float: right;
position: relative;
top: -5px;
@include border-radius(4px);
text-shadow: none;
&.state-label-green {
background: #4A4;
color: #FFF;
}
&.state-label-red {
background: #DA4E49;
color: #FFF;
}
}
.dropdown-menu > li > a {
text-shadow: none;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background: #29b;
}
/**
* nav-pills
*
*/
.nav-pills {
.active a {
background: $primary_color;
}
> li > a {
@include border-radius(0);
}
&.nav-stacked {
> li > a {
border-left: 4px solid #EEE;
padding: 12px;
color: #777;
}
> .active > a {
border-color: $primary_color;
background: none;
color: #333;
font-weight: bolder;
}
&.nav-stacked-menu {
li > a {
padding: 16px;
}
}
}
&.nav-pills-small {
> li > a {
padding: 8px 12px;
font-size: 12px;
}
}
}
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
/**
* nav-tabs
*
*/
.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
font-weight: bold;
}
}
}
&.nav-small-tabs > li > a { padding: 6px 9px; }
}
/**
* fix to keep tooltips position in top navigation bar
*
*/
.navbar .nav > li {
position: relative;
white-space: nowrap;
}
/*
* Twitter bootstrap with GitLab customizations/additions
*
* Some unused bootstrap compontents like panels are not included.
* Other components like tabs are modified to GitLab style.
*
*/
$font-size-base: 13px !default;
$nav-pills-active-link-hover-bg: $bg_style_color;
$pagination-active-bg: $bg_style_color;
// Core variables and mixins
@import "bootstrap/variables";
@import "bootstrap/mixins";
// Reset
@import "bootstrap/normalize";
@import "bootstrap/print";
// Core CSS
@import "bootstrap/scaffolding";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/grid";
@import "bootstrap/tables";
@import "bootstrap/forms";
// Components
@import "bootstrap/component-animations";
@import "bootstrap/dropdowns";
@import "bootstrap/button-groups";
@import "bootstrap/input-groups";
@import "bootstrap/navs";
@import "bootstrap/navbar";
@import "bootstrap/breadcrumbs";
@import "bootstrap/pagination";
@import "bootstrap/pager";
@import "bootstrap/labels";
@import "bootstrap/badges";
@import "bootstrap/jumbotron";
@import "bootstrap/thumbnails";
@import "bootstrap/alerts";
@import "bootstrap/progress-bars";
@import "bootstrap/list-group";
@import "bootstrap/wells";
@import "bootstrap/close";
// Components w/ JavaScript
@import "bootstrap/modals";
@import "bootstrap/tooltip";
@import "bootstrap/popovers";
@import "bootstrap/carousel";
// Utility classes
.clearfix {
@include clearfix();
}
.center-block {
@include center-block();
}
.pull-right {
float: right !important;
}
.pull-left {
float: left !important;
}
.hide {
display: none;
}
.show {
display: block !important;
}
.invisible {
visibility: hidden;
}
.text-hide {
@include text-hide();
}
.hidden {
display: none !important;
visibility: hidden !important;
}
.affix {
position: fixed;
}
@import "bootstrap/responsive-utilities";
// Labels
.label {
padding: 2px 4px;
font-size: 12px;
font-style: normal;
font-weight: normal;
display: inline-block;
&.label-gray {
background-color: #eee;
color: #999;
text-shadow: none;
}
&.label-inverse {
background-color: #333333;
}
}
// Nav tabs
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
font-weight: bold;
}
}
}
&.nav-small-tabs > li > a {
padding: 6px 9px;
}
}
.nav-tabs > li > a,
.nav-pills > li > a {
color: #666;
}
.nav-small > li > a {
padding: 3px 5px;
font-size: 12px;
}
/*
* Callouts from Bootstrap3 docs
*
* Not quite alerts, but custom and helpful notes for folks reading the docs.
* Requires a base and modifier class.
*/
/* Common styles for all types */
.bs-callout {
margin: 20px 0;
padding: 20px;
border-left: 3px solid #eee;
color: #666;
background: #f9f9f9;
}
.bs-callout h4 {
margin-top: 0;
margin-bottom: 5px;
}
.bs-callout p:last-child {
margin-bottom: 0;
}
/* Variations */
.bs-callout-danger {
background-color: #fdf7f7;
border-color: #eed3d7;
color: #b94a48;
}
.bs-callout-warning {
background-color: #faf8f0;
border-color: #faebcc;
color: #8a6d3b;
}
.bs-callout-info {
background-color: #f4f8fa;
border-color: #bce8f1;
color: #34789a;
}
.bs-callout-success {
background-color: #dff0d8;
border-color: #5cA64d;
color: #3c763d;
}
// Breadcrumb
ul.breadcrumb {
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
font-size: 16px;
}
}
/**
* fix to keep tooltips position in top navigation bar
*
*/
.navbar .nav > li {
position: relative;
white-space: nowrap;
}
html {
overflow-y: scroll;
}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin-bottom: 20px;
}
.container {
padding-top: 0;
z-index: 5;
}
.container .content {
margin: 0 0;
}
......@@ -79,11 +79,15 @@
color: $style_color;
text-shadow: 0 1px 1px #FFF;
font-size: 16px;
line-height: 40px;
line-height: 44px;
font-weight: normal;
}
@mixin md-typography {
img {
max-width: 100%;
}
*:first-child {
margin-top: 0;
}
......@@ -136,7 +140,7 @@
}
@mixin page-title {
color: $style_color;
color: #333;
font-size: 20px;
line-height: 1.5;
margin-top: 0px;
......
......@@ -4,6 +4,7 @@
$primary_color: #2FA0BB;
$link_color: #3A89A3;
$style_color: #474D57;
$bg_style_color: #2299BB;
$hover: #D9EDF7;
/**
......
......@@ -80,7 +80,7 @@
border-right: 1px solid #ccc;
text-align: right;
min-width: 35px;
max-width: 35px;
max-width: 50px;
width: 35px;
@include user-select(none);
a {
......@@ -399,8 +399,8 @@
.commits-compare-switch{
background: url("switch_icon.png") no-repeat center center;
width: 22px;
height: 22px;
width: 32px;
height: 32px;
text-indent: -9999px;
float: left;
margin-right: 9px;
......@@ -481,6 +481,10 @@ li.commit {
font-family: $monospace_font;
}
.str-truncated {
max-width: 70%;
}
.commit-row-message {
color: #333;
font-weight: 500;
......
.dashboard {
@extend .row;
.activities {
}
.side {
@extend .pull-right;
.ui-box {
margin: 0px;
box-shadow: none;
......@@ -20,7 +14,7 @@
.search-text-input {
float:left;
@extend .span2;
@extend .col-md-2;
}
.btn {
margin-left: 5px;
......@@ -32,14 +26,15 @@
.dash-filter {
margin: 7px 0;
padding: 4px 6px;
width: 202px;
width: 220px;
float: left;
height: inherit;
}
}
@media (max-width: 1200px) {
.dashboard .dash-filter {
width: 132px;
width: 150px;
}
}
......@@ -66,41 +61,37 @@
}
.project-row, .group-row {
padding: 10px 15px !important;
padding: 10px 12px !important;
font-size: 14px;
line-height: 24px;
.namespace-name {
color: #666;
font-weight: bold;
a {
display: block;
}
.project-name, .group-name {
font-size: 15px;
font-weight: 500;
}
.arrow {
float: right;
padding: 10px 5px;
padding: 0px 5px;
margin: 0;
font-size: 20px;
color: #666;
}
.last-activity {
float: right;
font-size: 12px;
color: #AAA;
display: block;
margin-top: 5px;
.date {
color: #777;
}
}
}
.group-row {
.arrow {
padding: 2px 5px;
}
}
.project-access-icon {
margin-left: 10px;
float: left;
......@@ -111,10 +102,17 @@
padding: 8px 12px;
border-radius: 50px;
background: #f5f5f5;
width: 16px;
text-align: center;
i {
color: #BBB;
}
}
.dash-project-access-icon {
float: left;
margin-right: 3px;
color: #999;
margin-bottom: 10px;
width: 16px;
}
......@@ -34,15 +34,4 @@
margin: 5px 8px 0 8px;
}
}
.commit_message-group {
margin-top: 20px;
label {
font-size: 16px;
line-height: 20px;
}
textarea {
@extend .span8;
}
}
}
......@@ -75,6 +75,7 @@
margin-top: 4px;
margin-left: 0px;
max-width: 200px;
float: none;
}
p:last-child {
......@@ -147,7 +148,7 @@
float: left;
padding: 9px 6px;
font-size: 18px;
width: 26px;
width: 40px;
@include border-radius(3px);
}
......
......@@ -4,17 +4,24 @@
*/
header {
&.navbar-gitlab {
margin-bottom: 0;
min-height: 40px;
.navbar-inner {
height: 40px;
padding: 3px;
background: #F1F1F1;
border-bottom: 1px solid #DDD;
filter: none;
.nav > li > a {
color: $style_color;
text-shadow: 0 1px 0 #fff;
font-size: 14px;
padding: 10px;
line-height: 32px;
padding: 6px 10px;
&:hover {
background: none;
}
}
/** NAV block with links and profile **/
......@@ -35,9 +42,6 @@ header {
.app_logo {
float: left;
margin-right: 9px;
position: relative;
top: -3px;
padding-top: 3px;
a {
float: left;
......@@ -49,7 +53,7 @@ header {
background: url('logo-black.png') no-repeat center center;
background-size: 32px;
float: left;
height: 40px;
height: 46px;
width: 40px;
@include header-font;
text-indent: -9999px;
......@@ -75,7 +79,7 @@ header {
.profile-pic {
position: relative;
top: -4px;
top: -1px;
img {
width: 26px;
height: 26px;
......@@ -91,21 +95,25 @@ header {
.search {
margin-right: 10px;
margin-left: 10px;
margin-top: 8px;
form {
margin: 0;
padding: 0;
}
.search-input {
@extend .span3;
background-image: url("icon-search.png");
background-repeat: no-repeat;
background-position: 10px;
height: inherit;
padding: 4px 6px;
padding-left: 25px;
font-size: 13px;
@include border-radius(3px);
border: 1px solid #c6c6c6;
box-shadow: none;
@include transition(all 0.15s ease-in 0s);
&:focus {
@extend .span4;
}
}
}
......@@ -181,12 +189,26 @@ header {
.separator {
float: left;
height: 46px;
width: 1px;
width: 2px;
background: white;
border-left: 1px solid #DDD;
margin-top: -3px;
margin-left: 10px;
margin-right: 10px;
}
}
.search .search-input {
width: 300px;
&:focus {
width: 400px;
}
}
@media (max-width: 1200px) {
.search .search-input {
width: 200px;
&:focus {
width: 300px;
}
}
}
......@@ -77,8 +77,8 @@ input.check_all_issues {
@media (min-width: 800px) { .issues_filters select { width: 160px; } }
@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
@media (min-width: 800px) { .issues_bulk_update .chosen-container { min-width: 120px; } }
@media (min-width: 1200px) { .issues_bulk_update .chosen-container { min-width: 160px; } }
@media (min-width: 800px) { .issues_bulk_update .select2-container { min-width: 120px; } }
@media (min-width: 1200px) { .issues_bulk_update .select2-container { min-width: 160px; } }
.issues-holder {
.issues_filters {
......@@ -105,7 +105,7 @@ input.check_all_issues {
}
.issues_bulk_update {
.chosen-container {
.select2-container {
text-shadow: none;
}
}
......@@ -119,3 +119,11 @@ input.check_all_issues {
background-color: #f4f4f4;
}
}
.issue-show-labels .label {
padding: 6px 10px;
}
form.edit-issue {
margin: 0;
}
/* Login Page */
body.login-page{
.container > .content {
padding-top: 20px;
.login-page {
h1 {
font-size: 3em;
font-weight: 200;
}
}
.login-box{
.login-box{
width: 304px;
position: relative;
@include border-radius(5px);
margin: auto;
padding: 20px;
background: white;
}
}
.login-box .login-logo{
.login-logo{
margin: 10px 0 30px 0;
display: block;
}
}
.login-box input.text{background-color: #f1f1f1; font-size: 16px; @include border-radius(0); padding: 14px 10px; width: 280px}
.form-control {
background-color: #f1f1f1;
font-size: 16px;
padding: 14px 10px;
width: 280px;
height: auto;
.login-box input.text.top{
&.top {
@include border-radius(5px 5px 0 0);
margin-bottom: 0px;
}
}
.login-box input.text.bottom{
&.bottom {
@include border-radius(0 0 5px 5px);
border-top: 0;
margin-bottom: 20px;
}
}
.login-box input.text.middle{
&.middle {
border-top: 0;
margin-bottom:0px;
}
.login-box a.forgot{float: right; padding-top: 6px}
.remember_me {
text-align: left;
@include border-radius(0);
}
}
input {
margin: 2px;
.login-box a.forgot {
float: right;
padding-top: 6px
}
}
.devise-errors {
.devise-errors {
h2 {
font-size: 14px;
color: #a00;
}
}
}
......@@ -4,10 +4,6 @@
*
*/
.automerge_widget {
&.can_be_merged {
background: #DFF0D8;
}
form {
margin-bottom: 0;
.clearfix {
......@@ -15,31 +11,11 @@
}
}
.accept_group {
float: left;
border: 1px solid #ADA;
padding: 2px;
@include border-radius(5px);
background: #CEB;
.accept_merge_request {
font-size: 13px;
float: left;
}
.remove_branch_holder {
margin-left: 20px;
margin-right: 10px;
float: left;
}
.accept-group {
label {
color: #444;
text-align: left
}
margin: 5px;
margin-left: 20px;
}
.how_to_merge_link {
@extend .primary;
}
}
......@@ -53,11 +29,6 @@
}
}
.merge-in-progress {
@extend .padded;
@extend .append-bottom-10;
}
.mr_source_commit,
.mr_target_commit {
.commit {
......@@ -111,12 +82,8 @@
.merge-request-angle {
text-align: center;
margin: 0 auto;
background: #eee;
border-radius: 100px;
width: 60px;
line-height: 60px;
color: #777;
text-shadow: 0 1px 2px #FFF;
font-size: 2em;
line-height: 1.1;
}
.merge-request-form-info {
......@@ -128,8 +95,7 @@
font-weight: normal !important;
}
.chosen-container .chosen-single {
padding: 2px 0 2px 10px;
.select2-container .select2-single {
span {
font-weight: bold;
color: #555;
......
......@@ -6,6 +6,7 @@
border-bottom: 1px solid #E1E1E1;
ul {
padding: 0;
margin: auto;
height: 40px;
overflow: hidden;
......
......@@ -2,7 +2,7 @@
* Notes
*/
@-webkit-keyframes target-note {
@-webkit-keyframes targe3-note {
from { background:#fffff0; }
50% { background:#ffffd3; }
to { background:#fffff0; }
......@@ -119,9 +119,9 @@ ul.notes {
}
.file .notes_holder {
font-family: $sansFontFamily;
font-size: 13px;
line-height: 18px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
td {
border: 1px solid #ddd;
......@@ -138,7 +138,7 @@ ul.notes {
border-left: 1px solid #ddd !important;
}
&.notes_content {
background-color: $white;
background-color: #fff;
border-width: 1px 0;
padding-top: 0;
......@@ -257,12 +257,12 @@ ul.notes {
.file,
.discussion {
.new_note {
margin: 8px 5px 8px 0;
margin: 0;
border: none;
}
}
.new_note {
display: none;
.buttons {
float: left;
margin-top: 8px;
......@@ -303,7 +303,7 @@ ul.notes {
}
.note-image-attach {
@extend .span4;
@extend .col-md-4;
@extend .thumbnail;
margin-left: 45px;
}
......
.update-notifications {
margin-bottom: 0;
label {
margin-bottom: 0;
.radio-inline {
margin-right: 9%;
}
}
......@@ -17,7 +16,7 @@
legend {
border: none;
margin: 0;
margin-bottom: 10px;
}
}
}
......@@ -47,3 +46,62 @@
margin: 10px 0;
}
}
.user-show-username {
font-weight: 200;
color: #666;
}
/*
* Appearance settings
*
*/
.themes_opts {
label {
margin-right: 20px;
text-align: center;
.prev {
@extend .thumbnail;
height: 30px;
width: 175px;
margin-bottom: 10px;
&.classic {
background: #31363e;
}
&.default {
background: #f1f1f1;
}
&.modern {
background: #345;
}
&.gray {
background: #373737;
}
&.violet {
background: #547;
}
}
}
}
.code_highlight_opts {
margin-top: 10px;
label {
margin-right: 20px;
text-align: center;
.prev {
@extend .thumbnail;
height: 151px;
width: 220px;
margin-bottom: 10px;
}
}
}
......@@ -16,7 +16,7 @@
.project-home-panel {
border-bottom: 1px solid #DDD;
padding-bottom: 25px;
padding-bottom: 15px;
margin-bottom: 30px;
&.empty-project {
......@@ -27,7 +27,7 @@
.project-home-title {
font-size: 18px;
color: #777;
color: #444;
margin: 0;
line-height: 32px;
}
......@@ -40,25 +40,30 @@
.project-home-desc {
float: left;
color: #999;
color: #777;
margin-bottom: 10px;
}
.project-home-links {
float: right;
a {
margin-left: 10px;
font-weight: 500;
}
}
}
.visibility-level-label {
font-size: 14px;
font-size: 17px;
background: #f1f1f1;
padding: 8px 10px;
border-radius: 4px;
margin-left: 10px;
color: #888;
position: absolute;
margin-left: -55px;
text-shadow: 0 1px 1px #FFF;
width: 40px;
text-align: center;
padding: 6px;
i {
color: inherit;
......@@ -67,76 +72,53 @@
}
.git-clone-holder {
float: right;
border: 1px solid #E1E1E1;
@include border-radius(4px);
.project-home-dropdown + & {
margin-right: 45px;
}
input[type="text"],
.btn {
border: none;
@include border-radius(0px);
border-left: 1px solid #E1E1E1;
.btn,
.form-control {
border: 1px solid #E1E1E1;
box-shadow: none;
padding: 6px 10px;
padding: 6px 9px;
}
.btn {
float: left;
background: none;
color: #29b;
&:first-child {
@include border-radius-left(4px);
border-left: 0px;
}
&.active {
color: #333;
font-weight: bold;
}
}
input[type="text"] {
.form-control {
cursor: auto;
@extend .monospace;
background: #FAFAFA;
width: 100%;
}
}
.project-visibility-level-holder {
.controls {
padding-bottom: 9px;
}
.radio {
margin-bottom: 10px;
.controls {
input {
float: left;
}
.descr {
display: block;
margin-left: 1.5em;
&.restricted {
color: #888;
i {
margin: 0 3px;
font-size: 20px;
}
label {
float: none;
padding: 0;
margin: 0;
text-align: left;
}
}
.info {
display: block;
margin-top: 5px;
}
strong {
.option-title {
font-weight: bold;
display: inline-block;
width: 4em;
}
.option-descr {
margin-left: 24px;
color: #666;
}
i {
color: inherit;
}
}
......@@ -218,6 +200,9 @@ ul.nav.nav-projects-tabs {
.project-side {
.btn-block {
background-image: none;
.btn,
&.btn,
&.btn-group ul.dropdown-menu {
background-color: #F1f1f1;
border-color: #EEE;
&:hover {
......@@ -225,6 +210,18 @@ ul.nav.nav-projects-tabs {
border-color: #DDD;
}
}
&.btn-group-justified {
.btn {
width: 100%;
}
.dropdown-toggle {
width: 26px;
}
}
ul {
width: 100%;
}
}
.project-fork-icon {
float: left;
font-size: 26px;
......@@ -233,42 +230,10 @@ ul.nav.nav-projects-tabs {
}
}
.transfer-project .chosen-container {
.transfer-project .select2-container {
min-width: 200px;
}
/** Branch/tag selector **/
.project-refs-form {
margin: 0;
span {
background:none !important;
position:static !important;
width:auto !important;
height:auto !important;
}
}
.project-refs-select {
width: 120px;
}
.project-refs-form .chosen-container {
position: relative;
top: 0;
left: 0;
margin-right: 10px;
.chosen-single span {
font-weight: bold;
color: #555;
}
&.chosen-container-active {
.chosen-drop {
min-width: 400px;
}
.chosen-results {
max-height: 400px;
}
}
.deploy-project-label {
margin: 1px;
}
.snippet.file-holder {
.file-title {
.snippet-file-name {
padding: 4px 10px;
position: relative;
top: -4px;
left: -4px;
}
}
}
.my-snippets li:first-child {
h4 { margin-top: 0; }
padding-top: 0;
......
.themes_opts {
padding-left: 20px;
label {
width: 175px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height: 30px;
width: 175px;
margin-bottom: 10px;
&.classic {
background: #31363e;
}
&.default {
background: #f1f1f1;
}
&.modern {
background: #345;
}
&.gray {
background: #373737;
}
&.violet {
background: #547;
}
}
}
}
.code_highlight_opts {
padding-left: 20px;
label {
width: 220px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height: 151px;
width: 220px;
margin-bottom: 10px;
}
}
}
......@@ -24,10 +24,10 @@
th {
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid #CCC;
border-bottom: 1px solid #CCC !important;
}
td {
border-color: #F1F1F1;
border-color: #F1F1F1 !important;
}
&:hover {
td {
......@@ -49,6 +49,7 @@
.tree-item {
.tree-item-file-name {
max-width: 320px;
vertical-align: middle;
a {
&:hover {
......@@ -61,6 +62,14 @@
top:-1px;
}
}
.tree_commit {
max-width: 320px;
}
.tree_time_ago {
min-width: 135px;
}
}
.tree_author {
......@@ -111,5 +120,16 @@
.tree-ref-holder {
float: left;
margin-top: 5px;
margin-top: 8px;
}
.readme-holder {
border-top: 1px dashed #CCC;
padding-top: 10px;
h4 {
font-size: 14px;
margin-bottom: 20px;
color: #777;
}
}
......@@ -36,3 +36,8 @@
display: inline-block;
margin: 0 8px;
}
.votes-holder {
float: right;
width: 250px;
}
.wall-page {
.wall-note-form {
@extend .span12;
@extend .col-md-12;
margin: 0;
height: 140px;
......
h3.page-title .edit-wiki-header {
.title .edit-wiki-header {
width: 780px;
margin-left: auto;
margin-right: auto;
......
/** Chosen.js selectbox style override **/
.chosen-container {
min-width: 100px;
.chosen-single {
background: #EEE !important;
border: 1px solid #DDD !important;
@include box-shadow(none !important);
@include border-radius(4px !important);
}
.chosen-results li.highlighted {
background: #29b;
}
.chosen-drop {
margin-top: 10px;
border: 1px solid #DDD !important;
@include border-radius(4px !important);
}
.chosen-search input {
border: 1px solid #CCC !important;
@include box-shadow(none !important);
}
}
/** Select2 styling **/
.select2-container .select2-choice {
@include bg-light-gray-gradient;
}
.select2-container .select2-choice div {
border: none;
background: none;
}
.select2-drop {
padding-top: 8px;
}
.select2-no-results, .select2-searching {
padding: 7px;
color: #666;
}
.chosen-container .chosen-single div b {
background-position-y: 0px !important;
}
.chosen-container .chosen-drop .chosen-search input {
background-position-y: -24px !important;
}
class CommitLoadContext < BaseContext
def execute
result = {
commit: nil,
suppress_diff: false,
line_notes: [],
notes_count: 0,
note: nil,
status: :ok
}
commit = project.repository.commit(params[:id])
if commit
line_notes = project.notes.for_commit_id(commit.id).inline
result[:commit] = commit
result[:note] = project.build_commit_note(commit)
result[:line_notes] = line_notes
result[:notes_count] = project.notes.for_commit_id(commit.id).count
result[:branches] = project.repository.branch_names_contains(commit.id)
begin
result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff]
result[:force_suppress_diff] = commit.diff_force_suppress?
rescue Grit::Git::GitTimeout
result[:suppress_diff] = true
result[:status] = :huge_commit
end
end
result
end
end
class FilterContext
attr_accessor :items, :params
def initialize(items, params)
@items = items
@params = params
end
def execute
apply_filter(items)
end
def apply_filter items
if params[:project_id].present?
items = items.of_projects(params[:project_id])
end
if params[:search].present?
items = items.search(params[:search])
end
case params[:status]
when 'closed'
items.closed
when 'all'
items
else
items.opened
end
end
end
module Issues
class ListContext < BaseContext
attr_accessor :issues
def execute
@issues = @project.issues
@issues = case params[:state]
when 'all' then @issues
when 'closed' then @issues.closed
else @issues.opened
end
@issues = case params[:scope]
when 'assigned-to-me' then @issues.assigned_to(current_user)
when 'created-by-me' then @issues.authored(current_user)
else @issues
end
@issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present?
@issues = @issues.includes(:author, :project)
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
@issues = @issues.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
end
# Filter by specific milestone_id (or lack thereof)?
if params[:milestone_id].present?
@issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
end
# Sort by :sort param
@issues = sort(@issues, params[:sort])
@issues
end
private
def sort(issues, condition)
case condition
when 'newest' then issues.except(:order).order('created_at DESC')
when 'oldest' then issues.except(:order).order('created_at ASC')
when 'recently_updated' then issues.except(:order).order('updated_at DESC')
when 'last_updated' then issues.except(:order).order('updated_at ASC')
when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC")
when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC")
else issues
end
end
end
end
# Build collection of Merge Requests
# based on filtering passed via params for @project
class MergeRequestsLoadContext < BaseContext
def execute
merge_requests = @project.merge_requests
merge_requests = case params[:state]
when 'all' then merge_requests
when 'closed' then merge_requests.closed
else merge_requests.opened
end
merge_requests = case params[:scope]
when 'assigned-to-me' then merge_requests.assigned_to(current_user)
when 'created-by-me' then merge_requests.authored(current_user)
else merge_requests
end
merge_requests = merge_requests.page(params[:page]).per(20)
merge_requests = merge_requests.includes(:author, :source_project, :target_project).order("created_at desc")
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
merge_requests = merge_requests.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
end
# Filter by specific milestone_id (or lack thereof)?
if params[:milestone_id].present?
merge_requests = merge_requests.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
end
merge_requests
end
end
class SearchContext
attr_accessor :project_ids, :current_user, :params
def initialize(project_ids, user, params)
@project_ids, @current_user, @params = project_ids, user, params.dup
end
def execute
query = params[:search]
query = Shellwords.shellescape(query) if query.present?
return result unless query.present?
visibility_levels = @current_user ? [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ] : [ Gitlab::VisibilityLevel::PUBLIC ]
result[:projects] = Project.where("projects.id in (?) OR projects.visibility_level in (?)", project_ids, visibility_levels).search(query).limit(20)
# Search inside single project
single_project_search(Project.where(id: project_ids), query)
result
end
def single_project_search(projects, query)
project = projects.first if projects.length == 1
if params[:search_code].present?
result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo?
else
result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20)
result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20)
result[:wiki_pages] = []
end
end
def result
@result ||= {
projects: [],
merge_requests: [],
issues: [],
wiki_pages: [],
blobs: []
}
end
end
class TestHookContext < BaseContext
def execute
hook = project.hooks.find(params[:id])
data = GitPushService.new.sample_data(project, current_user)
hook.execute(data)
end
end
......@@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController
end
def transfer
result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin)
result = ::Projects::TransferService.new(@project, current_user, project: params).execute(:admin)
if result
redirect_to [:admin, @project]
......
......@@ -47,7 +47,7 @@ class Admin::UsersController < Admin::ApplicationController
@user.admin = (admin && admin.to_i > 0)
@user.created_by_id = current_user.id
@user.generate_password
@user.confirm!
@user.skip_confirmation!
respond_to do |format|
if @user.save
......
......@@ -161,6 +161,9 @@ class ApplicationController < ActionController::Base
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
headers['X-UA-Compatible'] = 'IE=edge'
headers['X-Content-Type-Options'] = 'nosniff'
headers['Strict-Transport-Security'] = 'max-age=31536000' if Gitlab.config.gitlab.https
end
def add_gon_variables
......@@ -223,7 +226,7 @@ class ApplicationController < ActionController::Base
end
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password) }
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :name, :password, :password_confirmation) }
end
end
......@@ -3,6 +3,8 @@ class DashboardController < ApplicationController
before_filter :load_projects, except: [:projects]
before_filter :event_filter, only: :show
before_filter :default_filter, only: [:issues, :merge_requests]
def show
# Fetch only 30 projects.
......@@ -41,26 +43,22 @@ class DashboardController < ApplicationController
@projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present?
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.includes(:namespace).sorted_by_activity
@projects = @projects.includes(:namespace)
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(30)
@labels = current_user.authorized_projects.tags_on(:labels)
@groups = current_user.authorized_groups
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.page(params[:page]).per(30)
end
# Get authored or assigned open merge requests
def merge_requests
@merge_requests = current_user.cared_merge_requests
@merge_requests = FilterContext.new(@merge_requests, params).execute
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end
# Get only assigned issues
def issues
@issues = current_user.assigned_issues
@issues = FilterContext.new(@issues, params).execute
@issues = FilteringService.new.execute(Issue, current_user, params)
@issues = @issues.recent.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project)
......@@ -75,4 +73,9 @@ class DashboardController < ApplicationController
def load_projects
@projects = current_user.authorized_projects.sorted_by_activity.non_archived
end
def default_filter
params[:scope] = 'assigned-to-me' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
end
end
......@@ -10,6 +10,8 @@ class GroupsController < ApplicationController
# Load group projects
before_filter :projects, except: [:new, :create]
before_filter :default_filter, only: [:issues, :merge_requests]
layout :determine_layout
before_filter :set_title, only: [:new, :create]
......@@ -45,18 +47,14 @@ class GroupsController < ApplicationController
end
end
# Get authored or assigned open merge requests
def merge_requests
@merge_requests = current_user.cared_merge_requests.of_group(@group)
@merge_requests = FilterContext.new(@merge_requests, params).execute
@merge_requests = @merge_requests.recent.page(params[:page]).per(20)
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.page(params[:page]).per(20)
end
# Get only assigned issues
def issues
@issues = current_user.assigned_issues.of_group(@group)
@issues = FilterContext.new(@issues, params).execute
@issues = @issues.recent.page(params[:page]).per(20)
@issues = FilteringService.new.execute(Issue, current_user, params)
@issues = @issues.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project)
respond_to do |format|
......@@ -132,4 +130,10 @@ class GroupsController < ApplicationController
'group'
end
end
def default_filter
params[:scope] = 'assigned-to-me' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
params[:group_id] = @group.id
end
end
......@@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController
end
def destroy
result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute
result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute
if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed"
......
......@@ -6,34 +6,35 @@ class Projects::CommitController < Projects::ApplicationController
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :require_non_empty_project
before_filter :commit
def show
result = CommitLoadContext.new(project, current_user, params).execute
return git_not_found! unless @commit
@commit = result[:commit]
@line_notes = project.notes.for_commit_id(commit.id).inline
@branches = project.repository.branch_names_contains(commit.id)
if @commit.nil?
git_not_found!
return
begin
@suppress_diff = true if commit.diff_suppress? && !params[:force_show_diff]
@force_suppress_diff = commit.diff_force_suppress?
rescue Grit::Git::GitTimeout
@suppress_diff = true
@status = :huge_commit
end
@suppress_diff = result[:suppress_diff]
@force_suppress_diff = result[:force_suppress_diff]
@note = result[:note]
@line_notes = result[:line_notes]
@branches = result[:branches]
@notes_count = result[:notes_count]
@target_type = :commit
@target_id = @commit.id
@note = project.build_commit_note(commit)
@notes_count = project.notes.for_commit_id(commit.id).count
@notes = project.notes.for_commit_id(@commit.id).not_inline.fresh
@noteable = @commit
@comments_allowed = @reply_allowed = true
@comments_target = { noteable_type: 'Commit',
commit_id: @commit.id }
@comments_target = {
noteable_type: 'Commit',
commit_id: @commit.id
}
respond_to do |format|
format.html do
if result[:status] == :huge_commit
if @status == :huge_commit
render "huge_commit" and return
end
end
......@@ -42,4 +43,8 @@ class Projects::CommitController < Projects::ApplicationController
format.patch { render text: @commit.to_patch }
end
end
def commit
@commit ||= project.repository.commit(params[:id])
end
end
......@@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController
end
def update
result = Files::UpdateContext.new(@project, current_user, params, @ref, @path).execute
result = Files::UpdateService.new(@project, current_user, params, @ref, @path).execute
if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed"
......
......@@ -24,15 +24,20 @@ class Projects::HooksController < Projects::ApplicationController
end
def test
TestHookContext.new(project, current_user, params).execute
TestHookService.new.execute(hook, current_user)
redirect_to :back
end
def destroy
@hook = @project.hooks.find(params[:id])
@hook.destroy
hook.destroy
redirect_to project_hooks_path(@project)
end
private
def hook
@hook ||= @project.hooks.find(params[:id])
end
end
......@@ -49,8 +49,8 @@ class Projects::IssuesController < Projects::ApplicationController
def show
@note = @project.notes.new(noteable: @issue)
@target_type = :issue
@target_id = @issue.id
@notes = @issue.notes.inc_author.fresh
@noteable = @issue
respond_with(@issue)
end
......@@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def bulk_update
result = Issues::BulkUpdateContext.new(project, current_user, params).execute
result = Issues::BulkUpdateService.new(project, current_user, params).execute
redirect_to :back, notice: "#{result[:count]} issues updated"
end
......@@ -116,7 +116,9 @@ class Projects::IssuesController < Projects::ApplicationController
end
def issues_filtered
@issues = Issues::ListContext.new(project, current_user, params).execute
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@issues = FilteringService.new.execute(Issue, current_user, params.merge(project_id: @project.id))
end
# Since iids are implemented only in 6.1
......
......@@ -17,7 +17,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
def index
@merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute
params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params.merge(project_id: @project.id))
@merge_requests = @merge_requests.page(params[:page]).per(20)
@sort = params[:sort].humanize
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
......@@ -123,7 +130,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if @merge_request.opened? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user)
@merge_request.automerge!(current_user, params[:merge_commit_message])
@status = true
else
@status = false
......@@ -198,6 +205,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def define_show_vars
# Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.inc_author.fresh
@discussions = Note.discussions_from_notes(@notes)
@noteable = @merge_request
# Get commits from repository
# or from cache if already merged
......@@ -205,9 +215,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
@target_type = :merge_request
@target_id = @merge_request.id
end
def allowed_to_merge?
......
......@@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController
def update
file_path = File.join(@path, File.basename(params[:file_name]))
result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute
result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed"
......
......@@ -2,71 +2,54 @@ class Projects::NotesController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_note!
before_filter :authorize_write_note!, only: [:create]
respond_to :js
before_filter :authorize_admin_note!, only: [:update, :destroy]
def index
@notes = Notes::LoadContext.new(project, current_user, params).execute
@target_type = params[:target_type].camelize
@target_id = params[:target_id]
@notes = Notes::LoadService.new(project, current_user, params).execute
if params[:target_type] == "merge_request"
@discussions = discussions_from_notes
end
notes_json = { notes: [] }
respond_to do |format|
format.html { redirect_to :back }
format.json do
render json: {
html: view_to_html_string("projects/notes/_notes")
@notes.each do |note|
notes_json[:notes] << {
id: note.id,
html: note_to_html(note)
}
end
end
render json: notes_json
end
def create
@note = Notes::CreateContext.new(project, current_user, params).execute
@target_type = params[:target_type].camelize
@target_id = params[:target_id]
@note = Notes::CreateService.new(project, current_user, params).execute
respond_to do |format|
format.html {redirect_to :back}
format.js
format.json { render_note_json(@note) }
format.html { redirect_to :back }
end
end
def destroy
@note = @project.notes.find(params[:id])
return access_denied! unless can?(current_user, :admin_note, @note)
@note.destroy
@note.reset_events_cache
def update
note.update_attributes(params[:note])
note.reset_events_cache
respond_to do |format|
format.js { render nothing: true }
format.json { render_note_json(note) }
format.html { redirect_to :back }
end
end
def update
@note = @project.notes.find(params[:id])
return access_denied! unless can?(current_user, :admin_note, @note)
@note.update_attributes(params[:note])
@note.reset_events_cache
def destroy
note.destroy
note.reset_events_cache
respond_to do |format|
format.js do
render js: { success: @note.valid?, id: @note.id, note: view_context.markdown(@note.note) }.to_json
end
format.html do
redirect_to :back
end
format.js { render nothing: true }
end
end
def delete_attachment
@note = @project.notes.find(params[:id])
@note.remove_attachment!
@note.update_attribute(:attachment, nil)
note.remove_attachment!
note.update_attribute(:attachment, nil)
respond_to do |format|
format.js { render nothing: true }
......@@ -77,35 +60,40 @@ class Projects::NotesController < Projects::ApplicationController
render text: view_context.markdown(params[:note])
end
protected
private
def discussion_notes_for(note)
@notes.select do |other_note|
note.discussion_id == other_note.discussion_id
end
def note
@note ||= @project.notes.find(params[:id])
end
def discussions_from_notes
discussion_ids = []
discussions = []
@notes.each do |note|
next if discussion_ids.include?(note.discussion_id)
# don't group notes for the main target
if note_for_main_target?(note)
discussions << [note]
else
discussions << discussion_notes_for(note)
discussion_ids << note.discussion_id
def note_to_html(note)
render_to_string(
"projects/notes/_note",
layout: false,
formats: [:html],
locals: { note: note }
)
end
def note_to_discussion_html(note)
render_to_string(
"projects/notes/_diff_notes_with_reply",
layout: false,
formats: [:html],
locals: { notes: [note] }
)
end
discussions
def render_note_json(note)
render json: {
id: note.id,
discussion_id: note.discussion_id,
html: note_to_html(note),
discussion_html: note_to_discussion_html(note)
}
end
# Helps to distinguish e.g. commit notes in mr notes list
def note_for_main_target?(note)
(@target_type.camelize == note.noteable_type && !note.for_diff_line?)
def authorize_admin_note!
return access_denied! unless can?(current_user, :admin_note, note)
end
end
......@@ -6,7 +6,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
before_filter :authorize_admin_project!, only: [:destroy, :create]
def index
@branches = @project.protected_branches.all
@branches = @project.protected_branches.to_a
@protected_branch = @project.protected_branches.new
end
......
......@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
storage_path = Rails.root.join("tmp", "repositories")
file_path = @repository.archive_repo(params[:ref], storage_path)
file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
if file_path
# Send file to user
......
......@@ -48,8 +48,8 @@ class Projects::SnippetsController < Projects::ApplicationController
def show
@note = @project.notes.new(noteable: @snippet)
@target_type = :snippet
@target_id = @snippet.id
@notes = @snippet.notes.fresh
@noteable = @snippet
end
def destroy
......
......@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController
end
def create
@project = ::Projects::CreateContext.new(current_user, params[:project]).execute
@project = ::Projects::CreateService.new(current_user, params[:project]).execute
respond_to do |format|
flash[:notice] = 'Project was successfully created.' if @project.saved?
......@@ -36,7 +36,7 @@ class ProjectsController < ApplicationController
end
def update
status = ::Projects::UpdateContext.new(@project, current_user, params).execute
status = ::Projects::UpdateService.new(@project, current_user, params).execute
respond_to do |format|
if status
......@@ -51,7 +51,7 @@ class ProjectsController < ApplicationController
end
def transfer
::Projects::TransferContext.new(project, current_user, params).execute
::Projects::TransferService.new(project, current_user, params).execute
end
def show
......@@ -89,7 +89,7 @@ class ProjectsController < ApplicationController
end
def fork
@forked_project = ::Projects::ForkContext.new(project, current_user).execute
@forked_project = ::Projects::ForkService.new(project, current_user).execute
respond_to do |format|
format.html do
......
......@@ -8,6 +8,7 @@ class Public::ProjectsController < ApplicationController
def index
@projects = Project.public_or_internal_only(current_user)
@projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(20)
end
end
class SearchController < ApplicationController
def show
project_id = params[:project_id]
group_id = params[:group_id]
include SearchHelper
project_ids = current_user.authorized_projects.map(&:id)
def show
@project = Project.find_by_id(params[:project_id]) if params[:project_id].present?
@group = Group.find_by_id(params[:group_id]) if params[:group_id].present?
if group_id.present?
@group = Group.find(group_id)
group_project_ids = @group.projects.map(&:id)
project_ids.select! { |id| group_project_ids.include?(id)}
elsif project_id.present?
@project = Project.find(params[:project_id])
project_ids.select! { |id| id == project_id.to_i}
if @project
return access_denied! unless can?(current_user, :download_code, @project)
@search_results = Search::ProjectService.new(@project, current_user, params).execute
else
@search_results = Search::GlobalService.new(current_user, params).execute
end
end
result = SearchContext.new(project_ids, current_user, params).execute
def autocomplete
term = params[:term]
@project = Project.find(params[:project_id]) if params[:project_id].present?
@ref = params[:project_ref] if params[:project_ref].present?
@projects = result[:projects]
@merge_requests = result[:merge_requests]
@issues = result[:issues]
@wiki_pages = result[:wiki_pages]
@blobs = Kaminari.paginate_array(result[:blobs]).page(params[:page]).per(20)
@total_results = @projects.count + @merge_requests.count + @issues.count + @wiki_pages.count + @blobs.total_count
render json: search_autocomplete_opts(term).to_json
end
end
......@@ -3,7 +3,7 @@ class UsersController < ApplicationController
def show
@user = User.find_by_username!(params[:username])
@projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id))
@projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace)
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
@title = @user.name
......
......@@ -72,7 +72,7 @@ module ApplicationHelper
def last_commit(project)
if project.repo_exists?
time_ago_with_tooltip(project.repository.commit.committed_date) + " ago"
time_ago_with_tooltip(project.repository.commit.committed_date)
else
"Never"
end
......@@ -136,14 +136,6 @@ module ApplicationHelper
Digest::SHA1.hexdigest string
end
def project_last_activity(project)
if project.last_activity_at
time_ago_with_tooltip(project.last_activity_at, 'bottom', 'last_activity_time_ago') + " ago"
else
"Never"
end
end
def authbutton(provider, size = 64)
file_name = "#{provider.to_s.split('_').first}_#{size}.png"
image_tag("authbuttons/#{file_name}",
......@@ -218,11 +210,15 @@ module ApplicationHelper
def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago')
capture_haml do
haml_tag :time, time_ago_in_words(date),
class: html_class, datetime: date, title: date.stamp("Aug 21, 2011 9:23pm"),
haml_tag :time, date.to_s,
class: html_class, datetime: date.getutc.iso8601, title: date.stamp("Aug 21, 2011 9:23pm"),
data: { toggle: 'tooltip', placement: placement }
haml_tag :script, "$('." + html_class + "').tooltip()"
haml_tag :script, "$('." + html_class + "').timeago().tooltip()"
end.html_safe
end
def render_markup(file_name, file_content)
GitHub::Markup.render(file_name, file_content).html_safe
end
end
module BroadcastMessagesHelper
def broadcast_styling(broadcast_message)
if(broadcast_message.color || broadcast_message.font)
"background-color:#{broadcast_message.color};color:#{broadcast_message.font}"
else
""
end
end
end
This diff is collapsed.
......@@ -90,14 +90,14 @@ module EventsHelper
if event.note? && event.note_commit?
project_commit_path(event.project, event.note_target)
else
url_for([event.project, event.note_target])
polymorphic_path([event.project, event.note_target], anchor: dom_id(event.target))
end
end
def event_note_title_html(event)
if event.note_target
if event.note_commit?
link_to project_commit_path(event.project, event.note_commit_id), class: "commit_short_id" do
link_to project_commit_path(event.project, event.note_commit_id, anchor: dom_id(event.target)), class: "commit_short_id" do
"#{event.note_target_type} #{event.note_short_commit_id}"
end
elsif event.note_project_snippet?
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment