Merge remote-tracking branch 'gitlabhq/master' into git_commit_fix

Conflicts:
	doc/install/installation.md
This commit is contained in:
David Barri 2012-11-11 21:27:55 +11:00
commit 93f0a8c9b3
369 changed files with 102667 additions and 1369 deletions

View file

@ -4,7 +4,7 @@ env:
before_install:
- sudo apt-get install libicu-dev -y
- sudo apt-get install libqt4-dev libqtwebkit-dev -y
- gem install charlock_holmes -v="0.6.8"
- gem install charlock_holmes -v="0.6.9"
branches:
only:
- 'master'

View file

@ -28,7 +28,7 @@ v 3.0.0
- Reject ssh keys that break gitolite
- [API] list one project hook
- [API] edit project hook
- [API] add project snippets list
- [API] list project snippets
- [API] allow to authorize using private token in HTTP header
- [API] add user creation

View file

@ -1,4 +1,4 @@
## Contribute to GitLab
## Contribute to GitLab
If you want to contribute to GitLab, follow this process:
@ -7,24 +7,20 @@ If you want to contribute to GitLab, follow this process:
3. Code
4. Create a pull request
We will only accept pull requests if:
We will only accept pull requests if:
* Your code has proper tests and all tests pass
* Your code can be merged w/o problems
* Your code can be merged w/o problems
* It won't break existing functionality
* It's quality code
* We like it :)
## [You may need a developer VM](https://github.com/gitlabhq/developer-vm)
For examples of feedback on pull requests please look at the [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
## Installation
Install the Gitlab development in a virtual machine with the [Gitlab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm). Installing it in a virtual machine makes it much easier to set up all the dependencies for integration testing.
## Running tests
To run the specs for GitLab, you need to run seeds for test db.
cd gitlabhq
rake db:seed_fu RAILS_ENV=test
Then you can run the test suite with rake:
rake gitlab:test
For more information on running the tests please read the [development tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)

31
Gemfile
View file

@ -11,9 +11,9 @@ end
gem "rails", "3.2.8"
# Supported DBs
gem "sqlite3", :group => :sqlite
gem "mysql2", :group => :mysql
gem "pg", :group => :postgres
gem "sqlite3", group: :sqlite
gem "mysql2", group: :mysql
gem "pg", group: :postgres
# Auth
gem "devise", "~> 2.1.0"
@ -23,10 +23,11 @@ gem 'omniauth-twitter'
gem 'omniauth-github'
# GITLAB patched libs
gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
gem "omniauth-ldap", :git => "https://github.com/gitlabhq/omniauth-ldap.git", :ref => "f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e"
gem 'yaml_db', :git => "https://github.com/gitlabhq/yaml_db.git"
gem 'grack', :git => "https://github.com/gitlabhq/grack.git"
gem "grit", git: "https://github.com/gitlabhq/grit.git", ref: '7f35cb98ff17d534a07e3ce6ec3d580f67402837'
gem "omniauth-ldap", git: "https://github.com/gitlabhq/omniauth-ldap.git", ref: 'f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e'
gem 'yaml_db', git: "https://github.com/gitlabhq/yaml_db.git", ref: '98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd'
gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'
gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '212fd40bea61f3c6a167223768e7295dc32bbc10'
# Gitolite client (for work with gitolite-admin repo)
gem "gitolite", '1.1.0'
@ -35,7 +36,7 @@ gem "gitolite", '1.1.0'
gem "pygments.rb", "0.3.1"
# Language detection
gem "github-linguist", "~> 2.3.4" , :require => "linguist"
gem "github-linguist", "~> 2.3.4" , require: "linguist"
# API
gem "grape", "~> 0.2.1"
@ -83,9 +84,6 @@ gem 'resque_mailer'
# HTTP requests
gem "httparty"
# Handle encodings
gem "charlock_holmes"
# Colored output to console
gem "colored"
@ -114,8 +112,9 @@ group :assets do
end
group :development do
gem "annotate", git: "https://github.com/ctran/annotate_models.git"
gem "letter_opener"
gem "annotate", :git => "https://github.com/ctran/annotate_models.git"
gem 'quiet_assets', '1.0.1'
gem 'rack-mini-profiler'
end
@ -137,13 +136,13 @@ group :development, :test do
gem 'guard-spinach'
# Notification
gem 'rb-fsevent', :require => darwin_only('rb-fsevent')
gem 'growl', :require => darwin_only('growl')
gem 'rb-inotify', :require => linux_only('rb-inotify')
gem 'rb-fsevent', require: darwin_only('rb-fsevent')
gem 'growl', require: darwin_only('growl')
gem 'rb-inotify', require: linux_only('rb-inotify')
end
group :test do
gem "simplecov", :require => false
gem "simplecov", require: false
gem "shoulda-matchers"
gem 'email_spec'
gem 'resque_spec'

View file

@ -7,6 +7,7 @@ GIT
GIT
remote: https://github.com/gitlabhq/grack.git
revision: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
ref: ba46f3b0845c6a09d488ae6abdce6ede37e227e8
specs:
grack (1.0.0)
rack (~> 1.4.1)
@ -21,6 +22,14 @@ GIT
mime-types (~> 1.15)
posix-spawn (~> 0.3.6)
GIT
remote: https://github.com/gitlabhq/grit_ext.git
revision: 212fd40bea61f3c6a167223768e7295dc32bbc10
ref: 212fd40bea61f3c6a167223768e7295dc32bbc10
specs:
grit_ext (0.6.0)
charlock_holmes (~> 0.6.9)
GIT
remote: https://github.com/gitlabhq/omniauth-ldap.git
revision: f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e
@ -35,6 +44,7 @@ GIT
GIT
remote: https://github.com/gitlabhq/yaml_db.git
revision: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
ref: 98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd
specs:
yaml_db (0.2.2)
@ -90,7 +100,7 @@ GEM
carrierwave (0.6.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
charlock_holmes (0.6.8)
charlock_holmes (0.6.9)
childprocess (0.3.2)
ffi (~> 1.0.6)
chosen-rails (0.9.8.3)
@ -260,6 +270,8 @@ GEM
posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0)
pyu-ruby-sasl (0.0.3.3)
quiet_assets (1.0.1)
railties (~> 3.1)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
@ -411,7 +423,6 @@ DEPENDENCIES
capybara
capybara-webkit
carrierwave
charlock_holmes
chosen-rails
coffee-rails (= 3.2.2)
colored
@ -432,6 +443,7 @@ DEPENDENCIES
grack!
grape (~> 0.2.1)
grit!
grit_ext!
growl
guard-rspec
guard-spinach
@ -454,6 +466,7 @@ DEPENDENCIES
pg
pry
pygments.rb (= 0.3.1)
quiet_assets (= 1.0.1)
rack-mini-profiler
rails (= 3.2.8)
rails-dev-tweaks

View file

@ -1,2 +0,0 @@
web: bundle exec rails s -p $PORT -e production
worker: bundle exec rake environment resque:work RAILS_ENV=production QUEUE=*

19
ROADMAP.md Normal file
View file

@ -0,0 +1,19 @@
## GitLab Roadmap
### Common
* Help page for service tasks like repos import, backup etc
* Hide last push widget after following link
* Add comment events
* Dashboard/Project activity events filter
### Issues
* labels autocomplete via jquery autocomplete
* Import/Export issues
* Form: Assign to me link right to the selectbox
### Merge Request
* CI build status
* Save code fragments with MR comments

View file

@ -1 +1 @@
3.0.3
3.1.0pre

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -17,6 +17,8 @@
//= require modernizr
//= require chosen-jquery
//= require raphael
//= require g.raphael-min
//= require g.bar-min
//= require branch-graph
//= require ace-src-noconflict/ace
//= require_tree .

View file

@ -1,57 +1,47 @@
# Creates the variables for setting up GFM auto-completion
###
Creates the variables for setting up GFM auto-completion
###
# Emoji
window.autocompleteEmojiData = [];
window.autocompleteEmojiTemplate = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>";
data = []
template = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>"
window.autocompleteEmoji = {data, template}
# Team Members
window.autocompleteMembersUrl = "";
window.autocompleteMembersParams =
private_token: ""
page: 1
window.autocompleteMembersData = [];
url = '';
params = {private_token: '', page: 1}
window.autocompleteMembers = {data, url, params}
###
Add GFM auto-completion to all input fields, that accept GFM input.
###
# Add GFM auto-completion to all input fields, that accept GFM input.
window.setupGfmAutoComplete = ->
###
Emoji
###
$('.gfm-input').atWho ':',
data: autocompleteEmojiData,
tpl: autocompleteEmojiTemplate
$input = $('.js-gfm-input')
###
Team Members
###
$('.gfm-input').atWho '@', (query, callback) ->
# Emoji
$input.atWho ':',
data: autocompleteEmoji.data,
tpl: autocompleteEmoji.template
# Team Members
$input.atWho '@', (query, callback) ->
(getMoreMembers = ->
$.getJSON(autocompleteMembersUrl, autocompleteMembersParams)
.success (members) ->
# pick the data we need
newMembersData = $.map members, (m) -> m.name
$.getJSON(autocompleteMembers.url, autocompleteMembers.params).success (members) ->
# pick the data we need
newMembersData = $.map members, (m) -> m.name
# add the new page of data to the rest
$.merge autocompleteMembersData, newMembersData
# add the new page of data to the rest
$.merge autocompleteMembers.data, newMembersData
# show the pop-up with a copy of the current data
callback autocompleteMembersData[..]
# show the pop-up with a copy of the current data
callback autocompleteMembers.data[..]
# are we past the last page?
if newMembersData.length == 0
# set static data and stop callbacks
$('.gfm-input').atWho '@',
data: autocompleteMembersData
callback: null
else
# get next page
getMoreMembers()
# are we past the last page?
if newMembersData.length is 0
# set static data and stop callbacks
$input.atWho '@',
data: autocompleteMembers.data
callback: null
else
# get next page
getMoreMembers()
# so the next request gets the next page
autocompleteMembersParams.page += 1;
).call();
autocompleteMembers.params.page += 1
).call()

View file

@ -1,10 +0,0 @@
initGraphNav = ->
$('.graph svg').css 'position', 'relative'
$('body').bind 'keyup', (e) ->
if e.keyCode is 37 # left
$('.graph svg').animate left: '+=400'
else if e.keyCode is 39 # right
$('.graph svg').animate left: '-=400'
window.initGraphNav = initGraphNav

View file

@ -1,6 +1,5 @@
function switchToNewIssue(form){
function switchToNewIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
$(".issues_content").after(form);
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#new_issue_dialog").show("fade", { direction: "right" }, 150);
@ -10,9 +9,8 @@ function switchToNewIssue(form){
});
}
function switchToEditIssue(form){
function switchToEditIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
$(".issues_content").after(form);
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
@ -33,8 +31,8 @@ function switchFromEditIssue(){
function backToIssues(){
$("#edit_issue_dialog, #new_issue_dialog").hide("fade", { direction: "right" }, 150, function(){
$(".issues_content").show("fade", { direction: "left" }, 150, function() {
$("#edit_issue_dialog").remove();
$("#new_issue_dialog").remove();
$("#edit_issue_dialog").html("");
$("#new_issue_dialog").html("");
$('.add_new').show();
});
});

View file

@ -1,5 +0,0 @@
Loader =
html: (width) ->
$('<img>').attr src: '/assets/ajax-loader.gif', width: width
window.Loader = Loader

View file

@ -7,29 +7,32 @@ window.slugify = (text) ->
window.ajaxGet = (url) ->
$.ajax({type: "GET", url: url, dataType: "script"})
# Disable button if text field is empty
# Disable button if text field is empty
window.disableButtonIfEmptyField = (field_selector, button_selector) ->
field = $(field_selector)
closest_submit = field.closest("form").find(button_selector)
closest_submit.disable() if field.val() is ""
field.on "keyup", ->
if $(this).val() is ""
field.on "input", ->
if $(@).val() is ""
closest_submit.disable()
else
closest_submit.enable()
$ ->
# Click a .one_click_select field, select the contents
$(".one_click_select").live 'click', -> $(this).select()
$(".one_click_select").on 'click', -> $(@).select()
# Initialize chosen selects
$('select.chosen').chosen()
# Initialize tooltips
$('.has_tooltip').tooltip()
# Disable form buttons while a form is submitting
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
buttons = $('[type="submit"]', this)
buttons = $('[type="submit"]', @)
switch e.type
when 'ajax:beforeSend', 'submit'
@ -38,7 +41,7 @@ $ ->
buttons.enable()
# Show/Hide the profile menu when hovering the account box
$('.account-box').hover -> $(this).toggleClass('hover')
$('.account-box').hover -> $(@).toggleClass('hover')
# Focus search field by pressing 's' key
$(document).keypress (e) ->
@ -52,22 +55,22 @@ $ ->
# Commit show suppressed diff
$(".supp_diff_link").bind "click", ->
$(this).next('table').show()
$(this).remove()
$(@).next('table').show()
$(@).remove()
# Note markdown preview
$(document).on 'click', '#preview-link', (e) ->
$('#preview-note').text('Loading...')
$('#preview-note').text 'Loading...'
previewLinkText = if $(this).text() == 'Preview' then 'Edit' else 'Preview'
$(this).text(previewLinkText)
previewLinkText = if $(@).text() is 'Preview' then 'Edit' else 'Preview'
$(@).text previewLinkText
note = $('#note_note').val()
if note.trim().length == 0
$('#preview-note').text("Nothing to preview.")
if note.trim().length is 0
$('#preview-note').text 'Nothing to preview.'
else
$.post $(this).attr('href'), {note: note}, (data) ->
$.post $(@).attr('href'), {note: note}, (data) ->
$('#preview-note').html(data)
$('#preview-note, #note_note').toggle()
@ -79,14 +82,14 @@ $ ->
$.fn.extend chosen: (options) ->
default_options = search_contains: "true"
$.extend default_options, options
_chosen.apply this, [default_options]
_chosen.apply @, [default_options]
# Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: ->
$(this).attr('disabled', 'disabled').addClass('disabled')
$(@).attr('disabled', 'disabled').addClass('disabled')
# Enable an element and remove the 'disabled' Bootstrap class
$.fn.extend enable: ->
$(this).removeAttr('disabled').removeClass('disabled')
$(@).removeAttr('disabled').removeClass('disabled')
)(jQuery)

View file

@ -115,4 +115,15 @@ var MergeRequest = {
$(".merge_in_progress").hide();
$(".automerge_widget.already_cannot_be_merged").show();
}
};
/*
* Filter merge requests
*/
function merge_requestsPage() {
$("#assignee_id").chosen();
$("#milestone_id").chosen();
$("#milestone_id, #assignee_id").on("change", function(){
$(this).closest("form").submit();
});
}

View file

@ -5,3 +5,10 @@ $ ->
$('.milestone-issue-filter li').toggleClass('active')
$('.milestone-issue-filter tr[data-closed]').toggleClass('hide')
false
$('.milestone-merge-requests-filter tr[data-closed]').addClass('hide')
$('.milestone-merge-requests-filter ul.nav li a').click ->
$('.milestone-merge-requests-filter li').toggleClass('active')
$('.milestone-merge-requests-filter tr[data-closed]').toggleClass('hide')
false

View file

@ -22,3 +22,10 @@ $ ->
# Ref switcher
$('.project-refs-select').on 'change', ->
$(@).parents('form').submit()
class @GraphNav
@init: ->
$('.graph svg').css 'position', 'relative'
$('body').bind 'keyup', (e) ->
$('.graph svg').animate(left: '+=400') if e.keyCode is 37 # left
$('.graph svg').animate(left: '-=400') if e.keyCode is 39 # right

View file

@ -1,6 +0,0 @@
$ ->
$('#snippets-table .snippet').live 'click', (e) ->
if e.target.nodeName isnt 'A' and e.target.nodeName isnt 'INPUT'
location.href = $(@).attr 'url'
e.stopPropagation()
false

View file

@ -17,23 +17,21 @@ $ ->
"ajax:beforeSend": -> $('.tree_progress').addClass("loading")
"ajax:complete": -> $('.tree_progress').removeClass("loading")
# Maintain forward/back history while browsing the file tree
# Maintain forward/back history while browsing the file tree
((window) ->
History = window.History
$ = window.jQuery
document = window.document
((window) ->
History = window.History
$ = window.jQuery
document = window.document
# Check to see if History.js is enabled for our Browser
unless History.enabled
return false
# Check to see if History.js is enabled for our Browser
unless History.enabled
return false
$('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
History.pushState(null, null, $(@).attr('href'))
return false
$ ->
$('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
History.pushState(null, null, $(@).attr('href'))
return false
History.Adapter.bind window, 'statechange', ->
state = History.getState()
window.ajaxGet(state.url)
)(window)
History.Adapter.bind window, 'statechange', ->
state = History.getState()
window.ajaxGet(state.url)
)(window)

View file

@ -670,3 +670,16 @@ pre {
padding:0;
}
}
.milestone .progress {
margin-bottom: 0;
margin-top:4px;
}
.float-link {
float:left;
margin-right:15px;
.s16 {
margin-right:5px;
}
}

View file

@ -26,8 +26,10 @@
.underlined { border-bottom: 1px solid #CCC; }
.no-borders { border:none; }
.vlink { color: $link_color !important; }
.underlined_link { text-decoration: underline; }
.borders { border: 1px solid #ccc; @include shade; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
/** PILLS & TABS**/
.nav-pills a:hover { background-color:#888; }
@ -66,10 +68,10 @@
.alert-message.error { @extend .alert-error; }
/** AVATARS **/
img.avatar { float:left; margin-right:15px; width:40px; border:1px solid #ddd; padding:1px; }
img.avatar.s16 { width:16px; height:16px; }
img.avatar.s24 { width:24px; height:24px; }
img.avatar.s32 { width:32px; height:32px; }
img.avatar { float:left; margin-right:12px; width:40px; border:1px solid #ddd; padding:1px; }
img.avatar.s16 { width:16px; height:16px; margin-right:6px; }
img.avatar.s24 { width:24px; height:24px; margin-right:8px; }
img.avatar.s32 { width:32px; height:32px; margin-right:10px; }
img.lil_av { padding-left: 4px; padding-right:3px; }
/** HELPERS **/

View file

@ -157,10 +157,15 @@
font-size:12px !important;
}
table.highlighttable .linenodiv pre {
text-align: right;
padding-right: 4px;
color:#666;
table.highlighttable .linenodiv {
a {
color: #666;
}
pre {
text-align: right;
padding-right: 4px;
color:#666;
}
}
}
}

View file

@ -21,7 +21,7 @@ ul {
.author { color: #999; }
p {
padding-top:5px;
padding-top: 1px;
margin:0;
color:#222;
img {
@ -31,3 +31,11 @@ ul {
}
}
}
ol, ul {
&.styled {
li {
padding:2px;
}
}
}

View file

@ -34,6 +34,11 @@ table {
border-color:#f1f1f1;
line-height:28px;
.s16 {
margin-top: 5px;
margin-right: 5px;
}
&:first-child {
border-left:1px solid #bbb;
}

View file

@ -3,10 +3,11 @@
@import 'font-awesome';
/** GitLab colors **/
$link_color:#3A89A3;
$blue_link: #2fa0bb;
$style_color: #474d57;
$link_color: #3A89A3;
$blue_link: #2FA0BB;
$style_color: #474D57;
$hover: #D9EDF7;
$hover_border: #ADF;
/** GitLab Fonts **/
@font-face { font-family: Korolev; src: font-url('korolev-medium-compressed.otf'); }
@ -19,9 +20,9 @@ $hover: #D9EDF7;
}
@mixin solid_shade {
-moz-box-shadow: 0 0 0 3px #eee;
-webkit-box-shadow: 0 0 0 3px #eee;
box-shadow: 0 0 0 3px #eee;
-moz-box-shadow: 0 0 0 3px #f1f1f1;
-webkit-box-shadow: 0 0 0 3px #f1f1f1;
box-shadow: 0 0 0 3px #f1f1f1;
}
@mixin border-radius($radius) {
@ -64,6 +65,14 @@ $hover: #D9EDF7;
background-image: -o-linear-gradient($from, $to);
}
@mixin bg-light-gray-gradient {
background:#f1f1f1;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
}
@mixin bg-gray-gradient {
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));

View file

@ -19,41 +19,14 @@
margin-right: 10px;
.chzn-drop {
margin:7px 0;
min-width: 400px;
border: 2px solid $blue_link;
@include border-radius(4px);
.chzn-results {
max-height:300px;
.group-result {
color: $blue_link;
}
.active-result {
&.highlighted {
background: $blue_link;
}
}
}
.chzn-search input {
min-width:365px;
}
}
.chzn-single {
@include bg-gray-gradient;
div {
background:transparent;
border-left:none;
}
span {
font-weight: normal;
}
}
}
/** Fix for Search Dropdown Border **/
@ -65,4 +38,55 @@
box-shadow: none;
}
}
.chzn-drop {
margin:7px 0;
min-width: 200px;
border: 1px solid #bbb;
border-radius:0;
.chzn-results {
margin-top: 5px;
max-height:300px;
.group-result {
color: $style_color;
border-bottom: 1px solid #EEE;
padding: 8px;
}
.active-result {
border-radius: 0;
&.highlighted {
background: $hover;
color: $style_color;
}
&.result-selected {
background: #EEE;
border-left: 4px solid #CCC;
}
}
}
.chzn-search {
@include bg-gray-gradient;
input {
min-width:165px;
border-color: #CCC;
}
}
}
.chzn-single {
@include bg-light-gray-gradient;
div {
background:transparent;
border-left:none;
}
span {
font-weight: normal;
}
}
}

View file

@ -47,12 +47,15 @@
padding-left: 32px;
}
.author,
.committer {
.author a,
.committer a {
font-size:14px;
line-height:22px;
text-shadow:0 1px 1px #fff;
color:#777;
&:hover {
color: #999;
}
}
.avatar {
@ -227,6 +230,9 @@
.commit-author-name {
color: #777;
&:hover {
color: #999;
}
}
}

View file

@ -43,6 +43,7 @@
.event-body {
p {
color:#555;
padding-top: 5px;
}
.event-info {
color:#666;
@ -115,3 +116,29 @@
margin: -3px;
}
}
/**
* Event filter
*
*/
.event_filter {
position: absolute;
width: 40px;
margin-left: -50px;
.filter_icon {
float: left;
border-left: 3px solid #4bc;
padding: 7px;
background: #f9f9f9;
margin-bottom: 10px;
img {
width:20px;
}
&.inactive {
border-left: 3px solid #EEE;
opacity: 0.5;
}
}
}

View file

@ -44,7 +44,7 @@
img.avatar {
width:32px;
margin-top:4px;
margin-top:1px;
}
}
}

View file

@ -71,7 +71,7 @@ li.merge_request {
padding:7px 10px;
img.avatar {
width: 32px;
margin-top: 4px;
margin-top: 1px;
}
p {
padding: 0px;
@ -121,3 +121,20 @@ li.merge_request {
.mr_direction_tip {
margin-top:40px
}
.merge_requests_form_box {
@extend .main_box;
.merge_requests_middle_box {
@extend .middle_box_content;
height:30px;
.merge_requests_assignee {
@extend .span6;
float:left;
}
.merge_requests_milestone {
@extend .span4;
float:left;
}
}
}

View file

@ -57,10 +57,7 @@
padding-right: 8px;
img.avatar {
border: 0 none;
float: none;
margin-right: 0;
padding: 0;
margin-top: 0;
width: 16px;
}
}
@ -75,6 +72,15 @@
}
}
}
.blame {
img.avatar {
border: 0 none;
float: none;
margin: 0;
padding: 0;
}
}
}
.tree-btn-group {

View file

@ -37,9 +37,6 @@
background-image: -o-linear-gradient(#595D63 6.6%, #202227);
background-position:0 0;
color:#fff;
i {
@extend .icon-white;
}
}
border: 1px solid #31363E;

View file

@ -70,9 +70,6 @@
color:#ccc;
&:hover {
color:#fff;
i {
@extend .icon-white;
}
}
border: none;
box-shadow:none;

View file

@ -21,7 +21,7 @@ class CommitLoadContext < BaseContext
result[:notes_count] = line_notes.count + project.commit_notes(commit).count
begin
result[:suppress_diff] = true if commit.diffs.size > 200 && !params[:force_show_diff]
result[:suppress_diff] = true if commit.diffs.size > Commit::DIFF_SAFE_SIZE && !params[:force_show_diff]
rescue Grit::Git::GitTimeout
result[:suppress_diff] = true
result[:status] = :huge_commit

View file

@ -1,3 +1,5 @@
# Build collection of Merge Requests
# based on filtering passed via params for @project
class MergeRequestsLoadContext < BaseContext
def execute
type = params[:f]
@ -9,8 +11,21 @@ class MergeRequestsLoadContext < BaseContext
when 'closed' then merge_requests.closed
when 'assigned-to-me' then merge_requests.opened.assigned(current_user)
else merge_requests.opened
end.page(params[:page]).per(20)
end
merge_requests.includes(:author, :project).order("closed, created_at desc")
merge_requests = merge_requests.page(params[:page]).per(20)
merge_requests = merge_requests.includes(:author, :project).order("closed, 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

View file

@ -13,6 +13,7 @@ class SearchContext
result[:projects] = Project.where(id: project_ids).search(query).limit(10)
result[:merge_requests] = MergeRequest.where(project_id: project_ids).search(query).limit(10)
result[:issues] = Issue.where(project_id: project_ids).search(query).limit(10)
result[:wiki_pages] = Wiki.where(project_id: project_ids).search(query).limit(10)
result
end
@ -20,7 +21,8 @@ class SearchContext
@result ||= {
projects: [],
merge_requests: [],
issues: []
issues: [],
wiki_pages: []
}
end
end

View file

@ -9,19 +9,28 @@ class ApplicationController < ActionController::Base
helper_method :abilities, :can?
rescue_from Gitlab::Gitolite::AccessDenied do |exception|
log_exception(exception)
render "errors/gitolite", layout: "errors", status: 500
end
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
render "errors/encoding", layout: "errors", status: 500
end
rescue_from ActiveRecord::RecordNotFound do |exception|
log_exception(exception)
render "errors/not_found", layout: "errors", status: 404
end
protected
def log_exception(exception)
application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace
application_trace.map!{ |t| " #{t}\n" }
logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}"
end
def reject_blocked!
if current_user && current_user.blocked
sign_out current_user

View file

@ -1,7 +1,6 @@
# Controller for viewing a file's blame
class BlobController < ProjectResourceController
include ExtractsPath
include Gitlab::Encode
# Authorize
before_filter :authorize_read_project!
@ -12,16 +11,9 @@ class BlobController < ProjectResourceController
def show
if @tree.is_blob?
if @tree.text?
encoding = detect_encoding(@tree.data)
mime_type = encoding ? "text/plain; charset=#{encoding}" : "text/plain"
else
mime_type = @tree.mime_type
end
send_data(
@tree.data,
type: mime_type,
type: @tree.mime_type,
disposition: 'inline',
filename: @tree.name
)

View file

@ -1,12 +1,17 @@
class DashboardController < ApplicationController
respond_to :html
before_filter :event_filter, only: :index
def index
@groups = Group.where(id: current_user.projects.pluck(:group_id))
@projects = current_user.projects_with_events
@projects = @projects.page(params[:page]).per(30)
@events = Event.in_projects(current_user.project_ids).limit(20).offset(params[:offset] || 0)
@events = Event.in_projects(current_user.project_ids)
@events = @event_filter.apply_filter(@events)
@events = @events.limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push
respond_to do |format|
@ -34,4 +39,8 @@ class DashboardController < ApplicationController
format.atom { render layout: false }
end
end
def event_filter
@event_filter ||= EventFilter.new(params[:event_filter])
end
end

View file

@ -31,7 +31,8 @@ class MilestonesController < ProjectResourceController
def show
@issues = @milestone.issues
@users = @milestone.participants
@users = UserDecorator.decorate(@milestone.participants)
@merge_requests = @milestone.merge_requests
respond_to do |format|
format.html

View file

@ -22,7 +22,7 @@ class ProfileController < ApplicationController
flash[:notice] = "Password was successfully updated. Please login with it"
redirect_to new_user_session_path
else
render action: "password"
render 'account'
end
end

View file

@ -1,4 +1,4 @@
require Rails.root.join('lib', 'gitlab', 'graph_commit')
require Rails.root.join('lib', 'gitlab', 'graph', 'json_builder')
class ProjectsController < ProjectResourceController
skip_before_filter :project, only: [:new, :create]
@ -79,7 +79,9 @@ class ProjectsController < ProjectResourceController
end
def graph
@days_json, @commits_json = Gitlab::GraphCommit.to_graph(project)
graph = Gitlab::Graph::JsonBuilder.new(project)
@days_json, @commits_json = graph.days_json, graph.commits_json
end
def destroy

View file

@ -1,5 +1,4 @@
class RefsController < ProjectResourceController
include Gitlab::Encode
# Authorize
before_filter :authorize_read_project!

View file

@ -16,9 +16,14 @@ class RepositoriesController < ProjectResourceController
@tags = @project.tags
end
def stats
@stats = Gitlab::GitStats.new(@project.repo, @project.root_ref)
@graph = @stats.graph
end
def archive
unless can?(current_user, :download_code, @project)
render_404 and return
render_404 and return
end

View file

@ -5,5 +5,6 @@ class SearchController < ApplicationController
@projects = result[:projects]
@merge_requests = result[:merge_requests]
@issues = result[:issues]
@wiki_pages = result[:wiki_pages]
end
end

View file

@ -26,15 +26,14 @@ class TreeController < ProjectResourceController
end
def update
file_editor = Gitlab::FileEditor.new(current_user, @project, @ref)
update_status = file_editor.update(
@path,
edit_file_action = Gitlab::Satellite::EditFileAction.new(current_user, @project, @ref, @path)
updated_successfully = edit_file_action.commit!(
params[:content],
params[:commit_message],
params[:last_commit]
)
if update_status
if updated_successfully
redirect_to project_tree_path(@project, @id), notice: "Your changes have been successfully commited"
else
flash[:notice] = "Your changes could not be commited, because the file has been changed"

View file

@ -47,21 +47,15 @@ class CommitDecorator < ApplicationDecorator
# Otherwise it will link to the author email as specified in the commit.
#
# options:
# avatar: true will prepend avatar image
def author_link(options)
text = if options[:avatar]
avatar = h.image_tag h.gravatar_icon(author_email), class: "avatar", width: 16
"#{avatar} #{author_name}"
else
author_name
end
team_member = @project.try(:team_member_by_name_or_email, author_name, author_email)
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def author_link(options = {})
person_link(options.merge source: :author)
end
if team_member.nil?
h.mail_to author_email, text.html_safe, class: "commit-author-link"
else
h.link_to text, h.project_team_member_path(@project, team_member), class: "commit-author-link"
end
# Just like #author_link but for the committer.
def committer_link(options = {})
person_link(options.merge source: :committer)
end
protected
@ -69,4 +63,30 @@ class CommitDecorator < ApplicationDecorator
def no_commit_message
"--no commit message"
end
# Private: Returns a link to a person. If the person has a matching user and
# is a member of the current @project it will link to the team member page.
# Otherwise it will link to the person email as specified in the commit.
#
# options:
# source: one of :author or :committer
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def person_link(options = {})
source_name = send "#{options[:source]}_name".to_sym
source_email = send "#{options[:source]}_email".to_sym
text = if options[:avatar]
avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size]
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
else
source_name
end
team_member = @project.try(:team_member_by_name_or_email, source_name, source_email)
if team_member.nil?
h.mail_to source_email, text.html_safe, class: "commit-#{options[:source]}-link"
else
h.link_to text, h.project_team_member_path(@project, team_member), class: "commit-#{options[:source]}-link"
end
end
end

View file

@ -8,14 +8,14 @@ class TreeDecorator < ApplicationDecorator
#parts = parts[0...-1] if is_blob?
yield(h.link_to("..", "#", remote: true)) if parts.count > max_links
yield(h.link_to("..", "#")) if parts.count > max_links
parts.each do |part|
part_path = File.join(part_path, part) unless part_path.empty?
part_path = part if part_path.empty?
next unless parts.last(2).include?(part) if parts.count > max_links
yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path)), remote: true))
yield(h.link_to(h.truncate(part, length: 40), h.project_tree_path(project, h.tree_join(ref, part_path))))
end
end
end

View file

@ -0,0 +1,11 @@
class UserDecorator < ApplicationDecorator
decorates :user
def avatar_image size = 16
h.image_tag h.gravatar_icon(self.email, size), class: "avatar #{"s#{size}"}", width: size
end
def tm_of(project)
project.team_member_by_id(self.id)
end
end

View file

@ -36,7 +36,7 @@ module ApplicationHelper
else
gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
user_email.strip!
"#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=identicon"
"#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=mm"
end
end

View file

@ -65,4 +65,9 @@ module CommitsHelper
end
end
def commit_to_html commit
if commit.model
escape_javascript(render 'commits/commit', commit: commit)
end
end
end

View file

@ -33,4 +33,22 @@ module EventsHelper
image_tag event_image_path
end
end
def event_filter_link key, tooltip
key = key.to_s
filter = @event_filter.options key
inactive = if @event_filter.active? key
nil
else
'inactive'
end
content_tag :div, class: "filter_icon #{inactive}" do
link_to dashboard_path(event_filter: filter), class: 'has_tooltip', 'data-original-title' => tooltip do
image_tag "event_filter_#{key}.png"
end
end
end
end

View file

@ -10,5 +10,9 @@ module ProjectsHelper
def link_to_project project
link_to project.name, project
end
def tm_path team_member
project_team_member_path(@project, team_member)
end
end

View file

@ -67,4 +67,29 @@ module TreeHelper
can?(current_user, :push_code, @project)
end
end
# Breadcrumb links for a Project and, if applicable, a tree path
def breadcrumbs
return unless @project && @ref
# Add the root project link and the arrow icon
crumbs = content_tag(:li) do
content_tag(:span, nil, class: 'arrow') +
link_to(@project.name, project_commits_path(@project, @ref))
end
if @path
parts = @path.split('/')
parts.each_with_index do |part, i|
crumbs += content_tag(:span, '/', class: 'divider')
crumbs += content_tag(:li) do
# The text is just the individual part, but the link needs all the parts before it
link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
end
end
end
crumbs.html_safe
end
end

View file

@ -1,9 +1,13 @@
class Commit
include ActiveModel::Conversion
include Gitlab::Encode
include StaticModel
extend ActiveModel::Naming
# Safe amount of files with diffs in one commit to render
# Used to prevent 500 error on huge commits by suppressing diff
#
DIFF_SAFE_SIZE = 100
attr_accessor :commit, :head, :refs
delegate :message, :authored_date, :committed_date, :parents, :sha,
@ -107,7 +111,7 @@ class Commit
end
def safe_message
@safe_message ||= utf8 message
@safe_message ||= message
end
def created_at
@ -119,7 +123,7 @@ class Commit
end
def author_name
utf8 author.name
author.name
end
# Was this commit committed by a different person than the original author?
@ -128,7 +132,7 @@ class Commit
end
def committer_name
utf8 committer.name
committer.name
end
def committer_email

View file

@ -7,8 +7,6 @@ class Issue < ActiveRecord::Base
acts_as_taggable_on :labels
belongs_to :milestone
validates :description, length: { within: 0..2000 }
def self.open_for(user)

View file

@ -1,10 +1,11 @@
require Rails.root.join("app/models/commit")
require Rails.root.join("app/roles/static_model")
class MergeRequest < ActiveRecord::Base
include IssueCommonality
include Votes
attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch,
attr_accessible :title, :assignee_id, :closed, :target_branch, :source_branch, :milestone_id,
:author_id_of_changes
attr_accessor :should_remove_source_branch
@ -26,6 +27,10 @@ class MergeRequest < ActiveRecord::Base
where("source_branch LIKE :branch OR target_branch LIKE :branch", branch: branch_name)
end
def self.find_all_by_milestone(milestone)
where("milestone_id = :milestone_id", milestone_id: milestone)
end
def human_state
states = {
CAN_BE_MERGED => "can_be_merged",
@ -60,7 +65,7 @@ class MergeRequest < ActiveRecord::Base
end
def check_if_can_be_merged
self.state = if Gitlab::Merge.new(self, self.author).can_be_merged?
self.state = if Gitlab::Satellite::MergeAction.new(self.author, self).can_be_merged?
CAN_BE_MERGED
else
CANNOT_BE_MERGED
@ -167,7 +172,7 @@ class MergeRequest < ActiveRecord::Base
end
def automerge!(current_user)
if Gitlab::Merge.new(self, current_user).merge! && self.unmerged_commits.empty?
if Gitlab::Satellite::MergeAction.new(current_user, self).merge! && self.unmerged_commits.empty?
self.merge!(current_user.id)
true
end
@ -212,5 +217,6 @@ end
# st_diffs :text(4294967295
# merged :boolean default(FALSE), not null
# state :integer default(1), not null
# milestone_id :integer
#

View file

@ -3,6 +3,7 @@ class Milestone < ActiveRecord::Base
belongs_to :project
has_many :issues
has_many :merge_requests
validates :title, presence: true
validates :project, presence: true
@ -15,8 +16,20 @@ class Milestone < ActiveRecord::Base
User.where(id: issues.pluck(:assignee_id))
end
def open_items_count
self.issues.opened.count + self.merge_requests.opened.count
end
def closed_items_count
self.issues.closed.count + self.merge_requests.closed.count
end
def total_items_count
self.issues.count + self.merge_requests.count
end
def percent_complete
((self.issues.closed.count * 100) / self.issues.count).abs
((closed_items_count * 100) / total_items_count).abs
rescue ZeroDivisionError
100
end

View file

@ -23,13 +23,13 @@ class Note < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader
# Scopes
scope :common, where(noteable_id: nil)
scope :today, where("created_at >= :date", date: Date.today)
scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
scope :common, ->{ where(noteable_id: nil) }
scope :today, ->{ where("created_at >= :date", date: Date.today) }
scope :last_week, ->{ where("created_at >= :date", date: (Date.today - 7.days)) }
scope :since, ->(day) { where("created_at >= :date", date: (day)) }
scope :fresh, order("created_at ASC, id ASC")
scope :inc_author_project, includes(:project, :author)
scope :inc_author, includes(:author)
scope :fresh, ->{ order("created_at ASC, id ASC") }
scope :inc_author_project, ->{ includes(:project, :author) }
scope :inc_author, ->{ includes(:author) }
def self.create_status_change_note(noteable, author, status)
create({

View file

@ -104,8 +104,10 @@ class Project < ActiveRecord::Base
end
def repo_name
if path == "gitolite-admin"
errors.add(:path, " like 'gitolite-admin' is not allowed")
denied_paths = %w(gitolite-admin groups projects dashboard)
if denied_paths.include?(path)
errors.add(:path, "like #{path} is not allowed")
end
end

View file

@ -8,7 +8,7 @@ class Tree
def initialize(raw_tree, project, ref = nil, path = nil)
@project, @ref, @path = project, ref, path
@tree = if path.present?
raw_tree / path.dup.force_encoding('ascii-8bit')
raw_tree / path
else
raw_tree
end

View file

@ -15,6 +15,12 @@ class Wiki < ActiveRecord::Base
slug
end
class << self
def search(query)
where("title like :query OR content like :query", query: "%#{query}%")
end
end
protected
def self.regenerate_from wiki

View file

@ -6,6 +6,7 @@ module IssueCommonality
belongs_to :project
belongs_to :author, class_name: "User"
belongs_to :assignee, class_name: "User"
belongs_to :milestone
has_many :notes, as: :noteable, dependent: :destroy
validates :project, presence: true

View file

@ -41,7 +41,7 @@ module Repository
end
def satellite
@satellite ||= Gitlab::Satellite.new(self)
@satellite ||= Gitlab::Satellite::Satellite.new(self)
end
def has_post_receive_file?

View file

@ -43,7 +43,7 @@
%b
Owner:
%td
= @admin_project.owner.name
= @admin_project.owner_name || '(deleted)'
%tr
%td
%b

View file

@ -1,4 +1,4 @@
%h3.page_title Resque
%br
.ui-box
%iframe{src: resque_url, width: '100%', height: 600, style: "border: none"}
%iframe{src: resque_path, width: '100%', height: 600, style: "border: none"}

View file

@ -4,7 +4,4 @@
= nav_link(controller: :refs) do
= link_to 'Source', project_tree_path(@project, @ref)
%li.right
.input-prepend.project_clone_holder
%button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
%button{class: "btn small", :"data-clone" => @project.http_url_to_repo}= Gitlab.config.web_protocol.upcase
= text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
= render "shared/clone_panel"

View file

@ -15,7 +15,7 @@
.file_title
%i.icon-file
%span.file_name
= @tree.name.force_encoding('utf-8')
= @tree.name
%small= number_to_human_size @tree.size
%span.options= render "tree/blob_actions"
.file_content.blame
@ -24,9 +24,7 @@
- commit = Commit.new(commit)
- commit = CommitDecorator.decorate(commit)
%tr
%td.author
= image_tag gravatar_icon(commit.author_email, 16)
= commit.author_name
%td.author= commit.author_link avatar: true, size: 16
%td.blame_commit
&nbsp;
%code= link_to commit.short_id, project_commit_path(@project, commit)
@ -34,4 +32,4 @@
%td.lines
= preserve do
%pre
= Gitlab::Encode.utf8 lines.join("\n")
= lines.join("\n")

View file

@ -4,9 +4,8 @@
%strong= link_to "Browse Code »", project_tree_path(@project, commit), class: "right"
%p
= link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
%strong.commit-author-name= commit.author_name
%span.dash &ndash;
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
= commit.author_link avatar: true, size: 24
&nbsp;
= link_to_gfm truncate(commit.title, length: 50), project_commit_path(@project, commit.id), class: "row_title"
%span.committed_ago

View file

@ -18,16 +18,15 @@
.commit-info
.row
.span5
= image_tag gravatar_icon(@commit.author_email, 40), class: "avatar"
.author
%strong= @commit.author_name
%strong= @commit.author_link avatar: true, size: 40
authored
%time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.authored_date)} ago
- if @commit.different_committer?
.committer
&rarr;
%strong= @commit.committer_name
%strong= @commit.committer_link
committed
%time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")}
#{time_ago_in_words(@commit.committed_date)} ago

View file

@ -1,11 +1,11 @@
- if @suppress_diff
.alert-message.block-message
%p
%strong Warning! Large commit with more then 200 files changed.
%strong Warning! Large commit with more then #{Commit::DIFF_SAFE_SIZE} files changed.
%p To prevent performance issue we rejected diff information.
%p
But if you still want to see diff
= link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "dark"
= link_to "click this link", project_commit_path(@project, @commit, force_show_diff: true), class: "underlined_link"
%p.cgray
Showing #{pluralize(diffs.count, "changed file")}
@ -35,10 +35,10 @@
- if file.text?
= render "commits/text_file", diff: diff, index: i
- elsif file.image?
- if diff.renamed_file || diff.new_file || diff.deleted_file
- if diff.renamed_file || diff.new_file || diff.deleted_file
.diff_file_content_image
%img{class: image_diff_class(diff), src: "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"}
- else
- else
- old_file = (@commit.prev_commit.tree / diff.old_path)
.diff_file_content_image.img_compared
%img{class: "diff_image_removed", src: "data:#{file.mime_type};base64,#{Base64.encode64(old_file.data)}"}

View file

@ -16,6 +16,11 @@
Tags
%span.badge= @project.tags.length
= nav_link(controller: :repositories, action: :stats) do
= link_to stats_project_repository_path(@project) do
Stats
- if current_controller?(:commits) && current_user.private_token
%li.right
%span.rss-icon

View file

@ -2,14 +2,7 @@
- if @path.present?
%ul.breadcrumb
%li
%span.arrow
= link_to project_commits_path(@project) do
= @project.name
%span.divider
\/
%li
%a{href: "#"}= @path.split("/").join(" / ")
= breadcrumbs
%div{id: dom_id(@project)}
#commits_list= render "commits"

View file

@ -3,10 +3,17 @@
.activities.span8
= render "events/event_last_push", event: @last_push
= render 'shared/no_ssh'
.event_filter
= event_filter_link EventFilter.push, 'Push events'
= event_filter_link EventFilter.merged, 'Merge events'
= event_filter_link EventFilter.comments, 'Comments'
= event_filter_link EventFilter.team, 'Team'
- if @events.any?
.content_list= render @events
- else
%h4.nothing_here_message Projects activity will be displayed here
%p.nothing_here_message Projects activity will be displayed here
.loading.hide
.side
- if @groups.present?

View file

@ -14,8 +14,9 @@
= f.submit "Sign in", :class => "primary btn wide"
.right
= render :partial => "devise/shared/links"
- if devise_mapping.omniauthable?
%hr/
- resource_class.omniauth_providers.each do |provider|
%span
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
.clearfix
- if devise_mapping.omniauthable? && resource_class.omniauth_providers.present?
%div
- resource_class.omniauth_providers.each do |provider|
%span
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)

View file

@ -5,9 +5,10 @@
%hr
%p.slead
Your GitLab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
Your GitLab instance can perform HTTP POST requests on the following events: create_project, delete_project, create_user, delete_user, change_team_member.
%br
System Hooks can be used for logging or change information in LDAP server.
%br
System Hooks can be used, e.g. for logging or changing information in a LDAP server.
%br
%h5 Hooks request example:
= render "admin/hooks/data_ex"

View file

@ -12,7 +12,7 @@
= f.label :title do
%strong= "Subject *"
.input
= f.text_field :title, maxlength: 255, class: "xxlarge gfm-input", autofocus: true
= f.text_field :title, maxlength: 255, class: "xxlarge js-gfm-input", autofocus: true
.issue_middle_block
.issue_assignee
= f.label :assignee_id do
@ -37,7 +37,7 @@
.clearfix
= f.label :description, "Details"
.input
= f.text_area :description, maxlength: 2000, class: "xxlarge gfm-input", rows: 14
= f.text_area :description, maxlength: 2000, class: "xxlarge js-gfm-input", rows: 14
%p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.

View file

@ -1,5 +1,4 @@
:plain
var edit_issue_dialog = $("<div id='edit_issue_dialog'></div>");
edit_issue_dialog.html("#{escape_javascript(render('form'))}");
switchToEditIssue(edit_issue_dialog);
$("#edit_issue_dialog").html("#{escape_javascript(render('form'))}");
switchToEditIssue();

View file

@ -58,6 +58,8 @@
%ul#issues-table.unstyled.issues_table
= render "issues"
#new_issue_dialog
#edit_issue_dialog
:javascript
$(function(){

View file

@ -1,4 +1,3 @@
:plain
var new_issue_dialog = $("<div id='new_issue_dialog'></div>");
new_issue_dialog.html("#{escape_javascript(render('form'))}");
switchToNewIssue(new_issue_dialog);
$("#new_issue_dialog").html("#{escape_javascript(render('form'))}");
switchToNewIssue();

View file

@ -8,9 +8,7 @@
GITLAB
%span.separator
%h1.project_name= title
.search
= form_tag search_path, method: :get do |f|
= text_field_tag "search", nil, placeholder: "Search", class: "search-input"
= render "layouts/search"
.fbtn
- if current_user.is_admin?
= link_to admin_root_path, class: "btn small", title: "Admin area" do
@ -29,11 +27,3 @@
= link_to 'Logout', destroy_user_session_path, class: "logout", method: :delete
= render "layouts/init_auto_complete"
:javascript
$(function(){
$("#search").autocomplete({
source: #{raw search_autocomplete_source},
select: function(event, ui) { location.href = ui.item.url }
});
});

View file

@ -1,11 +1,11 @@
:javascript
$(function() {
autocompleteMembersUrl = "#{ "/api/v2/projects/#{@project.code}/members" if @project }";
autocompleteMembersParams.private_token = "#{current_user.authentication_token}";
autocompleteMembers.url = "#{ "/api/v2/projects/#{@project.code}/members" if @project }";
autocompleteMembers.params.private_token = "#{current_user.private_token}";
autocompleteEmojiData = #{raw emoji_autocomplete_source};
autocompleteEmoji.data = #{raw emoji_autocomplete_source};
// convert the list so that the items have the right format for completion
autocompleteEmojiData = $.map(autocompleteEmojiData, function(value) {
autocompleteEmoji.data = $.map(autocompleteEmoji.data, function(value) {
return {
name: value,
insert: value+':',

View file

@ -0,0 +1,11 @@
.search
= form_tag search_path, method: :get do |f|
= text_field_tag "search", nil, placeholder: "Search", class: "search-input"
:javascript
$(function(){
$("#search").autocomplete({
source: #{raw search_autocomplete_source},
select: function(event, ui) { location.href = ui.item.url }
});
});

View file

@ -28,16 +28,22 @@
%h4.cdark 2. Fill info
.clearfix
.main_box
.merge_requests_form_box
.top_box_content
= f.label :title do
= f.label :title do
%strong= "Title *"
.input= f.text_field :title, class: "input-xxlarge pad gfm-input", maxlength: 255, rows: 5
.middle_box_content
= f.label :assignee_id do
%i.icon-user
Assign to
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
.input= f.text_field :title, class: "input-xxlarge pad js-gfm-input", maxlength: 255, rows: 5
.merge_requests_middle_box
.merge_requests_assignee
= f.label :assignee_id do
%i.icon-user
Assign to
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
.merge_requests_milestone
= f.label :milestone_id do
%i.icon-time
Milestone
.input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
.control-group

View file

@ -10,6 +10,10 @@
%span.btn.small.disabled.grouped
%i.icon-comment
= merge_request.mr_and_commit_notes.count
- if merge_request.milestone_id?
%span.btn.small.disabled.grouped
%i.icon-time
= merge_request.milestone.title
%span.btn.small.disabled.grouped
= merge_request.source_branch
&rarr;

View file

@ -1,2 +1,2 @@
:plain
$(".mr_source_commit").html("#{escape_javascript(render 'commits/commit', commit: @commit)}");
$(".mr_source_commit").html("#{commit_to_html(@commit)}");

View file

@ -1,3 +1,2 @@
:plain
$(".mr_target_commit").html("#{escape_javascript(render 'commits/commit', commit: @commit)}");
$(".mr_target_commit").html("#{commit_to_html(@commit)}");

View file

@ -9,19 +9,26 @@
.ui-box
.title
%ul.nav.nav-pills
%li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
= link_to project_merge_requests_path(@project, f: 'open') do
Open
%li{class: ("active" if params[:f] == "closed")}
= link_to project_merge_requests_path(@project, f: "closed") do
Closed
%li{class: ("active" if params[:f] == 'assigned-to-me')}
= link_to project_merge_requests_path(@project, f: 'assigned-to-me') do
To Me
%li{class: ("active" if params[:f] == 'all')}
= link_to project_merge_requests_path(@project, f: 'all') do
All
.left
%ul.nav.nav-pills
%li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
= link_to project_merge_requests_path(@project, f: 'open', milestone_id: params[:milestone_id]) do
Open
%li{class: ("active" if params[:f] == "closed")}
= link_to project_merge_requests_path(@project, f: "closed", milestone_id: params[:milestone_id]) do
Closed
%li{class: ("active" if params[:f] == 'assigned-to-me')}
= link_to project_merge_requests_path(@project, f: 'assigned-to-me', milestone_id: params[:milestone_id]) do
To Me
%li{class: ("active" if params[:f] == 'all')}
= link_to project_merge_requests_path(@project, f: 'all', milestone_id: params[:milestone_id]) do
All
.right
= form_tag project_merge_requests_path(@project), id: "merge_requests_search_form", method: :get, class: :right do
= select_tag(:assignee_id, options_from_collection_for_select([unassigned_filter] + @project.users.all, "id", "name", params[:assignee_id]), prompt: "Assignee")
= select_tag(:milestone_id, options_from_collection_for_select([unassigned_filter] + @project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), prompt: "Milestone")
= hidden_field_tag :f, params[:f]
.clearfix
%ul.unstyled
= render @merge_requests
@ -35,3 +42,7 @@
.span4.right
%span.cgray.right #{@merge_requests.total_count} merge requests for this filter
:javascript
$(function() {
merge_requestsPage();
})

View file

@ -14,9 +14,13 @@
%strong.author= link_to_merge_request_author(@merge_request)
- if @merge_request.assignee
%cite.cgray and currently assigned to
%cite.cgray , currently assigned to
= image_tag gravatar_icon(@merge_request.assignee_email), width: 16, class: "lil_av"
%strong.author= link_to_merge_request_assignee(@merge_request)
- if @merge_request.milestone
- milestone = @merge_request.milestone
%cite.cgray and attached to milestone
%strong= link_to_gfm truncate(milestone.title, length: 20), project_milestone_path(milestone.project, milestone)
- if @merge_request.closed

View file

@ -1,18 +1,22 @@
%li{class: "milestone", id: dom_id(milestone) }
.right
- if milestone.issues.any?
%span.btn.small.disabled.grouped= pluralize milestone.issues.count, 'issues'
- if milestone.issues.count > 0
= link_to 'Browse Issues', project_issues_path(milestone.project, milestone_id: milestone.id), class: "btn small grouped"
- if can? current_user, :admin_milestone, milestone.project
= link_to 'Edit', edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped"
= link_to edit_project_milestone_path(milestone.project, milestone), class: "btn small edit-milestone-link grouped" do
%i.icon-edit
Edit
%h4
= link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone), class: "row_title"
= link_to_gfm truncate(milestone.title, length: 100), project_milestone_path(milestone.project, milestone)
%small
= milestone.expires_at
%br
.progress.progress-success.span3
.bar{style: "width: #{milestone.percent_complete}%;"}
&nbsp;
.row
.span4
.progress.progress-info
.bar{style: "width: #{milestone.percent_complete}%;"}
.span6
= link_to project_issues_path(milestone.project, milestone_id: milestone.id) do
= pluralize milestone.issues.count, 'Issue'
&nbsp;
= link_to project_merge_requests_path(milestone.project, milestone_id: milestone.id) do
= pluralize milestone.merge_requests.count, 'Merge Request'
&nbsp;
%span.light #{milestone.percent_complete}% complete

View file

@ -31,10 +31,10 @@
%h5
Progress:
%small
#{@milestone.issues.closed.count} closed
#{@milestone.closed_items_count} closed
&ndash;
#{@milestone.issues.opened.count} open
.progress.progress-success
#{@milestone.open_items_count} open
.progress.progress-info
.bar{style: "width: #{@milestone.percent_complete}%;"}
@ -58,15 +58,28 @@
%span.badge.badge-info ##{issue.id}
&ndash;
= link_to_gfm truncate(issue.title, length: 60), [@project, issue]
%br
.span6
%table
%table.milestone-merge-requests-filter
%thead
%th Participants
- @users.each do |user|
%tr
%th
%ul.nav.nav-pills
%li.active= link_to('Open Merge Requests', '#')
%li=link_to('All Merge Requests', '#')
- @merge_requests.each do |merge_request|
%tr{data: {closed: merge_request.closed}}
%td
= image_tag gravatar_icon(user.email, 24), width: "24"
&nbsp;
= user.name
= link_to [@project, merge_request] do
%span.badge.badge-info ##{merge_request.id}
&ndash;
= link_to_gfm truncate(merge_request.title, length: 60), [@project, merge_request]
%hr
%h6 Participants:
%div
- @users.each do |user|
= link_to tm_path(user.tm_of(@project)), class: 'float-link' do
= user.avatar_image
= user.name
.clearfix

View file

@ -8,7 +8,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
= f.text_area :note, size: 255, class: 'note-text gfm-input'
= f.text_area :note, size: 255, class: 'note-text js-gfm-input'
#preview-note.preview_note.hide
.hint
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.

View file

@ -13,7 +13,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
= f.hidden_field :line_code
= f.text_area :note, size: 255, class: 'line-note-text gfm-input'
= f.text_area :note, size: 255, class: 'line-note-text js-gfm-input'
.note_actions
.buttons
= f.submit 'Add note', class: "btn save-btn submit_note submit_inline_note", id: "submit_note"

View file

@ -4,7 +4,7 @@
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}
%td{align: "left", style: "padding: 20px 0 0;"}
%h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
= "You got granted #{@users_project.project_access_human} access to project"
= "You have been granted #{@users_project.project_access_human} access to project"
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}
%tr
%td{style: "font-size: 1px; line-height: 1px;", width: "21"}

View file

@ -14,7 +14,7 @@
%h3.page_title
Private token
%span.cred.right
keep it in secret!
keep it secret!
.padded
= form_for @user, url: profile_reset_private_token_path, method: :put do |f|
.data

Some files were not shown because too many files have changed in this diff Show more