Non-interactive AWS install by running a single script.

Merge branch 'master' into non-interactive-aws-install

Conflicts:
	doc/installation.md

Fix merge mess in installation.md
This commit is contained in:
Sytse Sijbrandij 2012-09-02 18:31:16 +02:00
parent eae41ad1df
commit b80dd3d242
215 changed files with 3829 additions and 3348 deletions

View file

@ -1,3 +0,0 @@
#this code temporarily disables notes for all controllers
# Footnotes::Filter.notes = []

View file

@ -1,8 +1,32 @@
v 2.9.0
- fixed inline notes bugs
- refactored rspecs
- refactored gitolite backend
- added factory_girl
- restyled projects list on dashboard
- ssh keys validation to prevent gitolite crash
- send notifications if changed premission in project
- scss refactoring. gitlab_bootstrap/ dir
- fix git push http body bigger than 112k problem
- list of labels page under issues tab
- API for milestones
- restyled buttons
v 2.8.1
- ability to disable gravatars
- improved MR diff logic
- ssh key help page
v 2.8.0 v 2.8.0
- Gitlab Flavored Markdown - Gitlab Flavored Markdown
- Bulk issues update - Bulk issues update
- Issues API - Issues API
- Cucumber coverage increased - Cucumber coverage increased
- Post-receive files fixed
- UI improved
- Application cleanup
- more cucumber
- capybara-webkit + headless
v 2.7.0 v 2.7.0
- Issue Labels - Issue Labels

10
Gemfile
View file

@ -54,7 +54,7 @@ gem "unicorn"
gem "acts-as-taggable-on", "2.3.1" gem "acts-as-taggable-on", "2.3.1"
# Decorators # Decorators
gem "drapper" gem "draper"
# Background jobs # Background jobs
gem "resque", "~> 1.20.0" gem "resque", "~> 1.20.0"
@ -92,7 +92,6 @@ end
group :development do group :development do
gem "letter_opener" gem "letter_opener"
gem "rails-footnotes"
gem "annotate", :git => "https://github.com/ctran/annotate_models.git" gem "annotate", :git => "https://github.com/ctran/annotate_models.git"
gem 'rack-mini-profiler' gem 'rack-mini-profiler'
end end
@ -108,15 +107,18 @@ group :development, :test do
gem "awesome_print" gem "awesome_print"
gem "database_cleaner" gem "database_cleaner"
gem "launchy" gem "launchy"
gem 'factory_girl_rails'
end end
group :test do group :test do
gem 'cucumber-rails', :require => false gem 'cucumber-rails', :require => false
gem 'minitest', ">= 2.10"
gem "turn", :require => false
gem "simplecov", :require => false gem "simplecov", :require => false
gem "shoulda-matchers" gem "shoulda-matchers"
gem 'email_spec' gem 'email_spec'
gem 'resque_spec' gem 'resque_spec'
gem "webmock" gem "webmock"
end end
group :production do
gem "gitlab_meta", '2.9'
end

View file

@ -99,7 +99,6 @@ GEM
acts-as-taggable-on (2.3.1) acts-as-taggable-on (2.3.1)
rails (~> 3.0) rails (~> 3.0)
addressable (2.2.8) addressable (2.2.8)
ansi (1.4.2)
arel (3.0.2) arel (3.0.2)
autotest (4.4.6) autotest (4.4.6)
ZenTest (>= 4.4.1) ZenTest (>= 4.4.1)
@ -156,7 +155,9 @@ GEM
railties (~> 3.1) railties (~> 3.1)
warden (~> 1.2.1) warden (~> 1.2.1)
diff-lcs (1.1.3) diff-lcs (1.1.3)
drapper (0.8.4) draper (0.17.0)
actionpack (~> 3.2)
activesupport (~> 3.2)
email_spec (1.2.1) email_spec (1.2.1)
mail (~> 2.2) mail (~> 2.2)
rspec (~> 2.0) rspec (~> 2.0)
@ -165,6 +166,11 @@ GEM
eventmachine (0.12.10) eventmachine (0.12.10)
execjs (1.4.0) execjs (1.4.0)
multi_json (~> 1.0) multi_json (~> 1.0)
factory_girl (4.0.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.0.0)
factory_girl (~> 4.0.0)
railties (>= 3.0.0)
ffaker (1.14.0) ffaker (1.14.0)
ffi (1.0.11) ffi (1.0.11)
foreman (0.47.0) foreman (0.47.0)
@ -172,6 +178,7 @@ GEM
gherkin (2.11.0) gherkin (2.11.0)
json (>= 1.4.6) json (>= 1.4.6)
git (1.2.5) git (1.2.5)
gitlab_meta (2.9)
grape (0.2.1) grape (0.2.1)
hashie (~> 1.2) hashie (~> 1.2)
multi_json multi_json
@ -218,7 +225,6 @@ GEM
treetop (~> 1.4.8) treetop (~> 1.4.8)
method_source (0.7.1) method_source (0.7.1)
mime-types (1.19) mime-types (1.19)
minitest (3.1.0)
modernizr (2.5.3) modernizr (2.5.3)
sprockets (~> 2.0) sprockets (~> 2.0)
multi_json (1.3.6) multi_json (1.3.6)
@ -258,8 +264,6 @@ GEM
activesupport (= 3.2.8) activesupport (= 3.2.8)
bundler (~> 1.0) bundler (~> 1.0)
railties (= 3.2.8) railties (= 3.2.8)
rails-footnotes (3.7.8)
rails (>= 3.0.0)
railties (3.2.8) railties (3.2.8)
actionpack (= 3.2.8) actionpack (= 3.2.8)
activesupport (= 3.2.8) activesupport (= 3.2.8)
@ -349,8 +353,6 @@ GEM
treetop (1.4.10) treetop (1.4.10)
polyglot polyglot
polyglot (>= 0.3.1) polyglot (>= 0.3.1)
turn (0.9.5)
ansi
tzinfo (0.3.33) tzinfo (0.3.33)
uglifier (1.0.3) uglifier (1.0.3)
execjs (>= 0.3.0) execjs (>= 0.3.0)
@ -389,11 +391,13 @@ DEPENDENCIES
cucumber-rails cucumber-rails
database_cleaner database_cleaner
devise (~> 2.1.0) devise (~> 2.1.0)
drapper draper
email_spec email_spec
factory_girl_rails
ffaker ffaker
foreman foreman
git git
gitlab_meta (= 2.9)
gitolite! gitolite!
grack! grack!
grape (~> 0.2.1) grape (~> 0.2.1)
@ -407,7 +411,6 @@ DEPENDENCIES
launchy launchy
letter_opener letter_opener
linguist (~> 1.0.0)! linguist (~> 1.0.0)!
minitest (>= 2.10)
modernizr (= 2.5.3) modernizr (= 2.5.3)
mysql2 mysql2
omniauth-ldap! omniauth-ldap!
@ -415,7 +418,6 @@ DEPENDENCIES
pygments.rb! pygments.rb!
rack-mini-profiler rack-mini-profiler
rails (= 3.2.8) rails (= 3.2.8)
rails-footnotes
raphael-rails (= 1.5.2) raphael-rails (= 1.5.2)
redcarpet (~> 2.1.1) redcarpet (~> 2.1.1)
resque (~> 1.20.0) resque (~> 1.20.0)
@ -432,7 +434,6 @@ DEPENDENCIES
stamp stamp
therubyracer therubyracer
thin thin
turn
uglifier (= 1.0.3) uglifier (= 1.0.3)
unicorn unicorn
webmock webmock

View file

@ -39,5 +39,6 @@ Email
## Contribute ## Contribute
[Development Tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
Want to help - send a pull request. Want to help - send a pull request.
We'll accept good pull requests. We'll accept good pull requests.

View file

@ -1 +1 @@
2.8.0pre 2.9.0pre

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
app/assets/images/merge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

View file

@ -72,7 +72,7 @@ $(document).ready(function(){
* Note markdown preview * Note markdown preview
* *
*/ */
$('#preview-link').on('click', function(e) { $(document).on('click', '#preview-link', function(e) {
$('#preview-note').text('Loading...'); $('#preview-note').text('Loading...');
var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview'); var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
@ -128,3 +128,23 @@ function showDiff(link) {
function ajaxGet(url) { function ajaxGet(url) {
$.ajax({type: "GET", url: url, dataType: "script"}); $.ajax({type: "GET", url: url, dataType: "script"});
} }
/**
* Disable button if text field is empty
*/
function disableButtonIfEmtpyField(field_selector, button_selector) {
field = $(field_selector);
if(field.val() == "") {
field.closest("form").find(button_selector).attr("disabled", "disabled").addClass("disabled");
}
field.on('keyup', function(){
var field = $(this);
var closest_submit = field.closest("form").find(button_selector);
if(field.val() == "") {
closest_submit.attr("disabled", "disabled").addClass("disabled");
} else {
closest_submit.removeAttr("disabled").removeClass("disabled");
}
})
}

View file

@ -5,6 +5,7 @@ function switchToNewIssue(form){
$('select#issue_milestone_id').chosen(); $('select#issue_milestone_id').chosen();
$("#new_issue_dialog").show("fade", { direction: "right" }, 150); $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
$('.top-tabs .add_new').hide(); $('.top-tabs .add_new').hide();
disableButtonIfEmtpyField("#issue_title", ".save-btn");
}); });
} }
@ -15,6 +16,7 @@ function switchToEditIssue(form){
$('select#issue_milestone_id').chosen(); $('select#issue_milestone_id').chosen();
$("#edit_issue_dialog").show("fade", { direction: "right" }, 150); $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
$('.add_new').hide(); $('.add_new').hide();
disableButtonIfEmtpyField("#issue_title", ".save-btn");
}); });
} }

View file

@ -1,14 +1,14 @@
var NoteList = { var NoteList = {
notes_path: null, notes_path: null,
target_params: null, target_params: null,
target_id: 0, target_id: 0,
target_type: null, target_type: null,
first_id: 0, first_id: 0,
last_id: 0, last_id: 0,
disable:false, disable:false,
init: init:
function(tid, tt, path) { function(tid, tt, path) {
this.notes_path = path + ".js"; this.notes_path = path + ".js";
this.target_id = tid; this.target_id = tid;
@ -24,15 +24,17 @@ init:
$('.delete-note').live('ajax:success', function() { $('.delete-note').live('ajax:success', function() {
$(this).closest('li').fadeOut(); }); $(this).closest('li').fadeOut(); });
$("#new_note").live("ajax:before", function(){ $(".note-form-holder").live("ajax:before", function(){
$(".submit_note").attr("disabled", "disabled"); $(".submit_note").attr("disabled", "disabled");
}) })
$("#new_note").live("ajax:complete", function(){ $(".note-form-holder").live("ajax:complete", function(){
$(".submit_note").removeAttr("disabled"); $(".submit_note").removeAttr("disabled");
}) })
$("#note_note").live("focus", function(){ disableButtonIfEmtpyField(".note-text", ".submit_note");
$(".note-text").live("focus", function(){
$(this).css("height", "80px"); $(this).css("height", "80px");
$('.note_advanced_opts').show(); $('.note_advanced_opts').show();
}); });
@ -46,31 +48,31 @@ init:
}, },
/** /**
* Load new notes to fresh list called 'new_notes_list': * Load new notes to fresh list called 'new_notes_list':
* - Replace 'new_notes_list' with new list every n seconds * - Replace 'new_notes_list' with new list every n seconds
* - Append new notes to this list after submit * - Append new notes to this list after submit
*/ */
initRefresh: initRefresh:
function() { function() {
// init timer // init timer
var intNew = setInterval("NoteList.getNew()", 10000); var intNew = setInterval("NoteList.getNew()", 10000);
}, },
replace: replace:
function(html) { function(html) {
$("#new_notes_list").html(html); $("#new_notes_list").html(html);
}, },
prepend: prepend:
function(id, html) { function(id, html) {
if(id != this.last_id) { if(id != this.last_id) {
$("#new_notes_list").prepend(html); $("#new_notes_list").prepend(html);
} }
}, },
getNew: getNew:
function() { function() {
// refersh notes list // refersh notes list
$.ajax({ $.ajax({
@ -80,7 +82,7 @@ getNew:
dataType: "script"}); dataType: "script"});
}, },
refresh: refresh:
function() { function() {
// refersh notes list // refersh notes list
$.ajax({ $.ajax({
@ -91,14 +93,14 @@ refresh:
}, },
/** /**
* Init load of notes: * Init load of notes:
* 1. Get content with ajax call * 1. Get content with ajax call
* 2. Set content of notes list with loaded one * 2. Set content of notes list with loaded one
*/ */
getContent: getContent:
function() { function() {
$.ajax({ $.ajax({
type: "GET", type: "GET",
@ -109,7 +111,7 @@ getContent:
dataType: "script"}); dataType: "script"});
}, },
setContent: setContent:
function(fid, lid, html) { function(fid, lid, html) {
this.last_id = lid; this.last_id = lid;
this.first_id = fid; this.first_id = fid;
@ -120,16 +122,14 @@ setContent:
}, },
/** /**
* Paging for old notes when scroll to bottom: * Paging for old notes when scroll to bottom:
* 1. Init scroll events with 'initLoadMore' * 1. Init scroll events with 'initLoadMore'
* 2. Load onlder notes with 'getOld' method * 2. Load onlder notes with 'getOld' method
* 3. append old notes to bottom of list with 'append' * 3. append old notes to bottom of list with 'append'
* *
*/ */
getOld:
getOld:
function() { function() {
$('.loading').show(); $('.loading').show();
$.ajax({ $.ajax({
@ -141,7 +141,7 @@ getOld:
dataType: "script"}); dataType: "script"});
}, },
append: append:
function(id, html) { function(id, html) {
if(this.first_id == id) { if(this.first_id == id) {
this.disable = true; this.disable = true;
@ -151,8 +151,7 @@ append:
} }
}, },
initLoadMore:
initLoadMore:
function() { function() {
$(document).endlessScroll({ $(document).endlessScroll({
bottomPixels: 400, bottomPixels: 400,
@ -166,4 +165,18 @@ initLoadMore:
} }
}); });
} }
};
var PerLineNotes = {
init:
function() {
$(".line_note_link, .line_note_reply_link").live("click", function(e) {
var form = $(".per_line_form");
$(this).closest("tr").after(form);
form.find("#note_line_code").val($(this).attr("line_code"));
form.show();
return false;
});
disableButtonIfEmtpyField(".line-note-text", ".submit_inline_note");
}
} }

View file

@ -7,8 +7,10 @@ function Projects() {
$('.new_project, .edit_project').live('ajax:before', function() { $('.new_project, .edit_project').live('ajax:before', function() {
$('.project_new_holder, .project_edit_holder').hide(); $('.project_new_holder, .project_edit_holder').hide();
$('.ajax_loader').show(); $('.save-project-loader').show();
}); });
$('form #project_default_branch').chosen(); $('form #project_default_branch').chosen();
disableButtonIfEmtpyField("#project_name", ".project-submit")
} }

View file

@ -1,11 +1,9 @@
.diff_file_header a,
.file_stats a {
color:$style_color;
}
/** LAYOUT **/ /** LAYOUT **/
body {
margin-bottom:20px;
}
.container { .container {
padding-top:0; padding-top:0;
z-index:5; z-index:5;
@ -40,30 +38,6 @@
color: $link_color; color: $link_color;
} }
.widget {
@include shade;
padding:20px;
margin-bottom:20px;
border: 1px solid #DDD;
border-radius: 5px;
background:#fafafa;
.link_holder {
background:#eee;
position:relative;
left:-20px;
top:20px;
padding:10px 20px;
width:100%;
border-top:1px solid #ccc;
a {
font-size:14px;
color:#666;
}
}
}
.help li { color:#111 } .help li { color:#111 }
.back_link { .back_link {
@ -88,16 +62,6 @@
padding-left:20px; padding-left:20px;
} }
.number {
border-radius: 4px;
text-shadow: none;
background: rgba(0,0,0,.12);
text-align: center;
padding: 2px 4px;
line-height:18px;
margin-left:2px;
}
table a code { table a code {
position: relative; position: relative;
top: -2px; top: -2px;
@ -129,26 +93,18 @@ table a code {
border-bottom:1px solid #ccc; border-bottom:1px solid #ccc;
h4 { h4 {
color:#444; color:#666;
font-size:22px; font-size:18px;
line-height:38px;
padding-top:5px; padding-top:5px;
margin:2px; margin:2px;
font-weight:normal;
} }
} }
.git_url_wrapper { .git_url_wrapper {
margin-right:50px margin-right:50px
} }
.file_stats {
span {
img {
width:14px;
float:left;
margin-right:6px;
padding:2px 0;
}
}
}
.handle:hover { .handle:hover {
cursor:move; cursor:move;
@ -172,10 +128,6 @@ span.update-author {
display:block; display:block;
} }
/** END UPDATE ITEM **/ /** END UPDATE ITEM **/
.ajax-tab-loading {
padding:40px;
display:none;
}
.dashboard-loader { .dashboard-loader {
float:left; float:left;
margin:10px; margin:10px;
@ -186,15 +138,110 @@ span.update-author {
font-weight:bold; font-weight:bold;
} }
a.project-update.titled { .neib {
position:relative; margin-right:10px;
padding-left:35% !important; }
.title-block {
padding:10px; .label {
width:35%; background-color: #474D57;
position:absolute;
left:0; &.label-issue {
top:0; background-color: #eee;
border: 1px solid #ccc;
padding:4px 6px;
color:#444;
text-shadow:0 0 1px #fff;
&.grouped {
float: left;
margin-right: 6px;
padding: 6px;
}
}
}
.event_label {
@extend .label;
background-color: #999;
&.pushed {
background-color: #4A97BD;
}
&.opened {
background-color: #469847;
}
&.closed {
background-color: #B94A48;
}
&.merged {
background-color: #2A2;
}
}
form {
@extend .form-horizontal;
.actions {
@extend .form-actions;
}
.clearfix {
@extend .control-group;
}
.input {
@extend .controls;
}
label {
@extend .control-label;
}
.xlarge {
@extend .input-xlarge;
}
.xxlarge {
@extend .input-xxlarge;
}
}
.field_with_errors {
display:inline;
}
ul.breadcrumb {
background:white;
border:none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
color:#474D57;
font-weight:bold;
font-size:14px;
}
.arrow {
background: url("images.png") no-repeat -85px -77px;
width: 19px;
height: 16px;
float: left;
position: relative;
left: -10px;
padding:0;
margin:0;
}
}
input[type=text] {
&.large_text {
padding:6px;
font-size:16px;
} }
} }
@ -270,40 +317,6 @@ p.time {
} }
/**
* Dashboard page
*
*/
.dashboard_category {
margin-bottom:30px;
h3 a {
color:#474D57;
&:hover {
text-decoration:underline;
}
}
.dashboard_block {
.dash_project_item {
margin-bottom:10px;
border:none;
padding:0px 5px;
.project_link {
color:#888;
&:hover {
color:#111;
.ico.project {
background-position:-209px -21px;
}
}
}
h4 {
color:#666;
}
}
}
}
.styled_image { .styled_image {
border:2px solid #ddd; border:2px solid #ddd;
} }
@ -393,39 +406,6 @@ p.time {
} }
} }
.btn {
&.very_small {
font-size:11px;
padding:2px 6px;
margin:2px;
}
&.grouped {
margin-right:7px;
float:left;
}
&.padded {
margin-right:3px;
padding:4px 10px 4px;
}
}
.prettyprint {
background-color: #fefbf3;
padding: 9px;
border: 1px solid rgba(0,0,0,.2);
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.1);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.1);
box-shadow: 0 1px 2px rgba(0,0,0,.1);
}
.hint {
font-style: italic;
color: #999;
}
.upvotes { .upvotes {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
@ -549,14 +529,6 @@ li.note {
} }
/**
* Milestones list
*
*/
.milestone {
@extend .wll;
}
/** /**
* Admin area * Admin area
@ -603,11 +575,10 @@ li.note {
* *
*/ */
.event_lp { .event_lp {
@extend .alert-info; @extend .ui-box;
color:#777;
margin-bottom:20px; margin-bottom:20px;
padding:8px; padding:8px;
border-style: solid;
border-width: 1px;
@include border-radius(4px); @include border-radius(4px);
min-height:22px; min-height:22px;
@ -621,88 +592,19 @@ li.note {
cursor:pointer; cursor:pointer;
} }
/**
* Issues, MRs legend
*
*/
.list_legend {
float:left;
margin-right:20px;
.icon {
width:12px;
height:12px;
float:left;
margin-right:5px;
margin-top: 2px;
@include border-radius(4px);
&.today{
background: #ADA;
border:1px solid #8B8;
}
&.closed {
background: #DDD;
border:1px solid #BBB;
}
&.yours {
background: #AAD;
border:1px solid #88B;
}
&.merged {
background: #DAD;
border:1px solid #B8B;
}
}
.text {
padding-bottom: 10px;
float:left;
}
}
.merge_request, .merge_request,
.issue { .issue {
.list_legend {
margin-right: 5px;
margin-top: 14px;
.icon {
width:8px;
height:8px;
float:left;
margin-right:5px;
@include border-radius(4px);
border:1px solid #ddd;
}
}
&.today{ &.today{
background: #EFE; background: #EFE;
border-color:#CEC; border-color:#CEC;
.icon {
background: #ADA;
border:1px solid #8B8;
}
} }
&.closed { &.closed {
background: #F5f5f5; background: #F5f5f5;
border-color:#E5E5E5; border-color:#E5E5E5;
.icon {
background: #DDD;
border:1px solid #BBB;
}
}
&.yours {
.icon {
background: #AAD;
border:1px solid #88B;
}
} }
&.merged { &.merged {
background: #F5f5f5; background: #F5f5f5;
border-color:#E5E5E5; border-color:#E5E5E5;
.icon {
background: #DAD;
border:1px solid #B8B;
}
} }
} }
@ -735,3 +637,11 @@ li.note {
font-size: 12px; font-size: 12px;
} }
} }
.error_message {
@extend .cred;
border-bottom: 1px solid #D21;
padding-bottom:20px;
text-align:center;
margin-bottom:10px;
}

View file

@ -1,818 +0,0 @@
body {
margin-bottom:20px;
}
a {
outline: none;
color: $link_color;
&:hover {
text-decoration:none;
color: $blue_link;
}
&.btn {
color: $style_color;
}
&.dark {
color: $style_color;
}
&.lined {
text-decoration:underline;
&:hover { text-decoration:underline; }
}
&.gray {
color:gray;
}
&.supp_diff_link {
text-align:center;
padding:20px 0;
background:#f1f1f1;
width:100%;
float:left;
}
&.neib {
margin-right:15px;
}
}
.neib {
margin-right:10px;
}
.alert-message {
@extend .alert;
&.success {
@extend .alert-success;
}
&.error {
@extend .alert-error;
}
}
.alert {
&.alert-well {
background:#ddd;
border:1px solid #ccc;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #ddd), to(#dfdfdf));
background-image: -webkit-linear-gradient(#ddd 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#ddd 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#ddd 6.6%, #dfdfdf);
color:#111;
}
}
h3, h4, h5, h6 {
line-height: 36px;
}
h5 {
font-size:14px;
}
table {
width:100%;
th {
padding-top: 9px;
font-weight: bold;
vertical-align: middle;
}
th, td {
padding: 10px 10px 9px;
line-height: 18px;
text-align: left;
}
&.bordered-table {
border: 1px solid #DDD;
border-collapse: separate;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
&.zebra-striped {
@extend .table-striped;
}
}
.btn {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f1f1f1), color-stop(25%, #f1f1f1), to(#e6e6e6));
background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
background-image: -moz-linear-gradient(top, #f1f1f1, #f1f1f1 25%, #e6e6e6);
background-image: -ms-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
background-image: -o-linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
background-image: linear-gradient(#f1f1f1, #f1f1f1 25%, #e6e6e6);
&:hover {
}
&.btn-primary {
background:$link_color;
border-color: #2A79A3;
&:hover {
background:$blue_link;
}
}
&.primary {
@extend .btn-primary;
}
&.success {
color: #fff;
text-shadow: 0 0 1px #111;
background: #5bb75b;;
font-weight: bold;
&:hover {
background-color: #51a351;
color: #fff;
}
}
&.danger,
&.btn-danger {
color:#fff;
background: #DA4E49;
border-color: #BD362F;
&:hover {
color:#fff;
background: #EE4E49;
}
}
&.danger {
@extend .btn-danger;
}
&.small {
@extend .btn-small;
}
&.active {
border-color:#aaa;
background-color:#ccc;
}
}
a:focus {
outline: none;
}
.nav-pills a:hover {
background-color:#888;
}
.nav-pills .active a {
background-color: $style_color;
}
.label {
background-color: #474D57;
&.label-important {
background-color: #B94A48;
}
&.label-issue {
background-color: #eee;
border: 1px solid #ccc;
padding:4px 6px;
color:#444;
text-shadow:0 0 1px #fff;
&.grouped {
float: left;
margin-right: 6px;
padding: 6px;
}
}
}
.nav-tabs > li > a, .nav-pills > li > a {
color:$style_color;
}
.nav-tabs > .active > a {
font-weight:bold;
}
/** COLORS **/
.cgray { color:gray; }
.cred { color:#D12F19; }
.cgreen { color:#44aa22; }
.cblack { color:#111; }
.cdark { color:#444 }
.cwhite { color:#fff !important }
.bgred { background: #F2DEDE !important}
/** COMMON STYLES **/
.left {
float:left;
}
.right {
float:right !important;
}
.width-50p{
width:50%;
}
.width-49p{
width:49%;
}
.width-30p{
width:30%;
}
.width-65p{
width:65%;
}
.width-100p{
width:100%;
}
.append-bottom-10 {
margin-bottom:10px;
}
.append-bottom-20 {
margin-bottom:20px;
}
.prepend-top-10 {
margin-top:10px;
}
.prepend-top-20 {
margin-top:20px;
}
.padded {
padding:20px;
}
.ipadded {
padding:20px !important;
}
.lborder {
border-left:1px solid #eee;
}
.borders {
border: 1px solid #ccc;
@include shade;
}
.no-borders {
border:none;
}
table.no-borders {
border:none;
tr, td { border:none }
}
.no-padding {
padding:0 !important;
}
.underlined {
border-bottom: 1px solid $border_color;
}
.vlink {
color: $link_color !important;
}
.pretty_label {
@include round-borders-all(4px);
padding:2px 4px;
background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8));
background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8);
background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8);
background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8);
color: #777;
border: 1px solid #DEDFE1;
&.branch {
border:none;
font-size:13px;
background: #474D57;
color:#fff;
font-weight:bold;
font-family: monospace;
}
}
.event_label {
@extend .label;
background-color: #999;
&.pushed {
background-color: #3A87AD;
}
&.opened {
background-color: #468847;
}
&.closed {
background-color: #B94A48;
}
&.merged {
background-color: #2A2;
}
}
img.avatar {
float:left;
margin-right:15px;
width:40px;
border:2px solid #ddd;
&.s16 {
width:16px;
}
&.s24 {
width:24px;
}
&.s32 {
width:32px;
}
}
img.lil_av {
padding-left: 4px;
padding-right:3px;
}
form {
@extend .form-horizontal;
.actions {
@extend .form-actions;
}
.clearfix {
@extend .control-group;
}
.input {
@extend .controls;
}
label {
@extend .control-label;
}
.xlarge {
@extend .input-xlarge;
}
.xxlarge {
@extend .input-xxlarge;
}
}
/**
* List li block element #1
*
*/
.wll {
background-color: #FFF;
padding: 10px 5px;
min-height: 20px;
border-bottom: 1px solid #eee;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&.smoke {
background-color:#f5f5f5;
}
&:hover {
background:$hover;
}
&:last-child { border:none }
p { padding-top:5px; margin:0; color:$style_color;}
.author { color: #999; }
p {
color:#222;
margin-bottom: 0;
img {
position:relative;
top:3px;
}
}
}
/**
* Block element #2
*
*/
.entry {
position: relative;
padding: 7px 15px;
margin-bottom: 18px;
color: #404040;
filter:none;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
background:#F1F1F1;
border: 1px solid #ccc;
p {
color:$style_color;
margin-bottom: 0;
img {
position:relative;
top:3px;
}
}
}
/**
* Big UI Block for show page content
*
*/
.ui-box {
background:#F9F9F9;
margin-bottom: 25px;
@include round-borders-all(4px);
border-color: #CCC;
@include solid_shade;
ul {
margin:0;
}
h5, .title {
padding: 0 10px;
@include round-borders-top(4px);
border-bottom: 1px solid #bbb;
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
&.small {
line-height: 28px;
font-size: 14px;
line-height:28px;
text-shadow: 0 1px 1px white;
}
form {
padding:9px 0;
margin:0px;
}
.nav-pills {
li {
padding:3px 0;
&.active a { background-color:$style_color; }
a {
border-radius:7px;
}
}
}
}
.bottom {
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
@include round-borders-bottom(4px);
border-bottom:none;
border-top: 1px solid #bbb;
}
&.padded {
h5, .title {
margin: -20px;
margin-bottom: 0;
padding: 5px 20px;
}
.middle_title {
background:#f5f5f5;
margin:20px -20px;
padding: 0 20px;
border-top:1px solid #eee;
border-bottom:1px solid #eee;
font-size:14px;
color:#777;
}
}
.row_title {
font-weight:bold;
color:#444;
&:hover {
color:#444;
text-decoration:underline;
}
}
li, .wll {
padding:10px;
&:first-child {
@include round-borders-top(4px);
border-top:none;
}
&:last-child {
@include round-borders-bottom(4px);
border:none;
}
}
}
table.admin-table {
@extend .table-bordered;
@extend .zebra-striped;
@include solid_shade;
th {
border-color: #CCC;
border-bottom: 1px solid #bbb;
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
}
}
.field_with_errors {
display:inline;
}
ul.breadcrumb {
background:white;
border:none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
color:#474D57;
font-weight:bold;
font-size:14px;
}
.arrow {
background: url("images.png") no-repeat -85px -77px;
width: 19px;
height: 16px;
float: left;
position: relative;
left: -10px;
padding:0;
margin:0;
}
}
.nothing_here_message {
text-align:center;
padding:20px;
color:#777;
}
/**
* UI box element
* contains top, middle, bottom blocks
*
*/
.main_box {
@extend .borders;
@extend .prepend-top-20;
@extend .append-bottom-20;
border-width:1px;
@include solid_shade;
img { max-width: 100%; }
pre {
code {
background: none !important;
}
}
.top_box_content,
.middle_box_content,
.bottom_box_content {
padding:15px;
pre {
background: none !important;
margin:0;
border:none;
padding:0;
}
}
.middle_box_content {
border-radius:0;
border:none;
font-size:12px;
background-color:#f5f5f5;
border:none;
border-top:1px solid #eee;
}
.bottom_box_content {
border-top:1px solid #eee;
}
}
input[type=text] {
&.large_text {
padding:6px;
font-size:16px;
}
}
p {
&.slead {
color:#456;
font-size:16px;
margin-bottom: 12px;
font-weight: 200;
line-height: 24px;
}
}
h3.page_title {
color:#456;
font-size:20px;
font-weight: normal;
line-height: 28px;
}
/**
* File content holder
*
*/
.file_holder {
border:1px solid #CCC;
margin-bottom:1em;
@include solid_shade;
.file_title {
border-bottom: 1px solid #bbb;
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
margin: 0;
font-weight: normal;
font-weight: bold;
text-align: left;
color: #666;
padding: 9px 10px;
height:18px;
.options {
float:right;
margin-top: -5px;
}
.file_name {
color:$style_color;
font-size:14px;
text-shadow: 0 1px 1px #fff;
small {
color:#999;
font-size:13px;
}
}
}
.file_content {
background:#fff;
font-size: 11px;
&.wiki {
font-size: 13px;
code {
padding:0 4px;
}
padding:20px;
h1, h2 {
line-height: 46px;
}
h3, h4 {
line-height: 40px;
}
}
&.image_file {
background:#eee;
text-align:center;
img {
padding:100px;
max-width:300px;
}
}
&.blob_file {
}
/**
* Blame file
*/
&.blame {
tr {
border-bottom: 1px solid #eee;
}
td {
padding:5px;
}
.author,
.blame_commit {
background:#f5f5f5;
vertical-align:top;
}
.lines {
pre {
padding:0;
margin:0;
background:none;
border:none;
}
}
}
&.logs {
background:#eee;
max-height: 700px;
overflow-y: auto;
ol {
margin-left:40px;
padding: 10px 0;
border-left: 1px solid #CCC;
margin-bottom:0;
background: white;
li {
color:#888;
p {
margin:0;
color:#333;
line-height:24px;
padding-left: 10px;
}
&:hover {
background:$hover;
}
}
}
}
/**
* Code file
*/
&.code {
padding:0;
td.code {
width: 100%;
.highlight {
margin-left: 55px;
overflow:auto;
overflow-y:hidden;
}
}
.highlight pre {
white-space: pre;
word-wrap:normal;
}
table.highlighttable {
border: none;
}
body.project-page table.highlighttable td { border: none }
table.highlighttable tr:hover { background:none;}
table.highlighttable pre{
line-height:16px !important;
font-size:12px !important;
}
table.highlighttable .linenodiv pre {
text-align: right;
padding-right: 4px;
color:#666;
}
}
}
}

View file

@ -0,0 +1,145 @@
/**
* ===================================
* Contain 3 main UI block elements:
* .main_box - for show pages
* .ui-box - for simple block & widgets
* ===================================
*/
/**
* UI box element
* contains top, middle, bottom blocks
*
*/
.main_box {
@extend .borders;
@extend .prepend-top-20;
@extend .append-bottom-20;
border-width:1px;
@include solid_shade;
img { max-width: 100%; }
pre {
code {
background: none !important;
}
}
.top_box_content,
.middle_box_content,
.bottom_box_content {
padding:15px;
pre {
background: none !important;
margin:0;
border:none;
padding:0;
}
}
.middle_box_content {
border-radius:0;
border:none;
font-size:12px;
background-color:#f5f5f5;
border:none;
border-top:1px solid #eee;
}
.bottom_box_content {
border-top:1px solid #eee;
}
}
/**
* Big UI Block for show page content
*
*/
.ui-box {
background:#F9F9F9;
margin-bottom: 25px;
@include round-borders-all(4px);
border-color: #CCC;
@include solid_shade;
ul {
margin:0;
}
h5, .title {
padding: 0 10px;
@include round-borders-top(4px);
@include bg-gray-gradient;
border-bottom: 1px solid #bbb;
&.small {
line-height: 28px;
font-size: 14px;
line-height:28px;
text-shadow: 0 1px 1px white;
}
form {
padding:9px 0;
margin:0px;
}
.nav-pills {
li {
padding:3px 0;
&.active a { background-color:$style_color; }
a {
border-radius:7px;
}
}
}
}
.bottom {
@include bg-gray-gradient;
@include round-borders-bottom(4px);
border-bottom:none;
border-top: 1px solid #bbb;
}
&.padded {
h5, .title {
margin: -20px;
margin-bottom: 0;
padding: 5px 20px;
}
.middle_title {
background:#f5f5f5;
margin:20px -20px;
padding: 0 20px;
border-top:1px solid #eee;
border-bottom:1px solid #eee;
font-size:14px;
color:#777;
}
}
.row_title {
font-weight:bold;
color:#444;
&:hover {
color:#444;
text-decoration:underline;
}
}
li, .wll {
padding:10px;
&:first-child {
@include round-borders-top(4px);
border-top:none;
}
&:last-child {
@include round-borders-bottom(4px);
border:none;
}
}
}

View file

@ -0,0 +1,105 @@
.btn {
background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #f7f7f7), to(#d5d5d5));
background-image: -webkit-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
background-image: -moz-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
background-image: -o-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
border-color:#aaa;
&:hover {
@include bg-gray-gradient;
border-color:#bbb;
color:#333;
}
&.primary {
background:#2a79A3;
border-color: #2A79A3;
background-image: -webkit-linear-gradient(#47A7b7 7.6%, #2585b5);
background-image: -moz-linear-gradient(#47A7b7 7.6%, #2585b5);
background-image: -o-linear-gradient(#47A7b7 7.6%, #2585b5);
color:#fff;
text-shadow: 0 1px 1px #268;
&:hover {
background:$blue_link;
color:#fff;
}
&.disabled {
color:#fff;
background:#29B;
}
}
&.success {
border-color: #4A4;
background-image: -webkit-linear-gradient(#82D482 7.6%, #22B442);
background-image: -moz-linear-gradient(#82D482 7.6%, #22B442);
background-image: -o-linear-gradient(#82D482 7.6%, #22B442);
color: #fff;
text-shadow: 0 1px 1px #141;
&:hover {
background: #6C6;
color: #fff;
}
&.disabled {
color:#fff;
background:#2b2;
}
}
&.save-btn {
@extend .wide;
@extend .primary;
}
&.cancel-btn {
float:right;
}
&.wide {
padding-left:30px;
padding-right:30px;
}
&.danger,
&.btn-danger {
color:#fff;
background: #DA4E49;
border-color: #BD362F;
&:hover {
color:#fff;
background: #EE4E49;
}
}
&.danger {
@extend .btn-danger;
}
&.small {
@extend .btn-small;
}
&.active {
border-color:#aaa;
background-color:#ccc;
}
&.very_small {
font-size:11px;
padding:2px 6px;
margin:2px;
}
&.grouped {
margin-right:7px;
float:left;
}
&.padded {
margin-right:3px;
padding:4px 10px 4px;
}
}

View file

@ -0,0 +1,52 @@
/** COLORS **/
.cgray { color:gray }
.cred { color:#D12F19 }
.cgreen { color:#4a2 }
.cblack { color:#111 }
.cdark { color:#444 }
.cwhite { color:#fff!important }
.bgred { background:#F2DEDE!important }
/** COMMON CLASSES **/
.left { float:left }
.right { float:right!important }
.width-50p { width:50% }
.width-49p { width:49% }
.width-30p { width:30% }
.width-65p { width:65% }
.width-100p { width:100% }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-20 { margin-bottom:20px }
.prepend-top-10 { margin-top:10px }
.prepend-top-20 { margin-top:20px }
.padded { padding:20px }
.ipadded { padding:20px!important }
.lborder { border-left:1px solid #eee }
.no-padding { padding:0 !important; }
.underlined { border-bottom: 1px solid #CCC; }
.no-borders { border:none; }
.vlink { color: $link_color !important; }
.borders { border: 1px solid #ccc; @include shade; }
.hint { font-style: italic; color: #999; }
/** PILLS & TABS**/
.nav-pills a:hover { background-color:#888; }
.nav-pills .active a { background-color: $style_color; }
.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
.nav-tabs > .active > a { font-weight:bold; }
/** ALERT MESSAGES **/
.alert-message { @extend .alert; }
.alert-messag.success { @extend .alert-success; }
.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.lil_av { padding-left: 4px; padding-right:3px; }
/** HELPERS **/
.nothing_here_message { text-align:center; padding:20px; color:#777; }
p.slead { color:#456; font-size:16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }

View file

@ -0,0 +1,156 @@
/**
* File content holder
*
*/
.file_holder {
border:1px solid #CCC;
margin-bottom:1em;
@include solid_shade;
.file_title {
border-bottom: 1px solid #bbb;
@include bg-gray-gradient;
margin: 0;
font-weight: normal;
font-weight: bold;
text-align: left;
color: #666;
padding: 9px 10px;
height:18px;
.options {
float:right;
margin-top: -5px;
}
.file_name {
color:$style_color;
font-size:14px;
text-shadow: 0 1px 1px #fff;
small {
color:#999;
font-size:13px;
}
}
}
.file_content {
background:#fff;
font-size: 11px;
&.wiki {
font-size: 13px;
code {
padding:0 4px;
}
padding:20px;
h1, h2 {
line-height: 46px;
}
h3, h4 {
line-height: 40px;
}
}
&.image_file {
background:#eee;
text-align:center;
img {
padding:100px;
max-width:300px;
}
}
&.blob_file {
}
/**
* Blame file
*/
&.blame {
tr {
border-bottom: 1px solid #eee;
}
td {
padding:5px;
}
.author,
.blame_commit {
background:#f5f5f5;
vertical-align:top;
}
.lines {
pre {
padding:0;
margin:0;
background:none;
border:none;
}
}
}
&.logs {
background:#eee;
max-height: 700px;
overflow-y: auto;
ol {
margin-left:40px;
padding: 10px 0;
border-left: 1px solid #CCC;
margin-bottom:0;
background: white;
li {
color:#888;
p {
margin:0;
color:#333;
line-height:24px;
padding-left: 10px;
}
&:hover {
background:$hover;
}
}
}
}
/**
* Code file
*/
&.code {
padding:0;
td.code {
width: 100%;
.highlight {
margin-left: 55px;
overflow:auto;
overflow-y:hidden;
}
}
.highlight pre {
white-space: pre;
word-wrap:normal;
}
table.highlighttable {
border: none;
}
body.project-page table.highlighttable td { border: none }
table.highlighttable tr:hover { background:none;}
table.highlighttable pre{
line-height:16px !important;
font-size:12px !important;
}
table.highlighttable .linenodiv pre {
text-align: right;
padding-right: 4px;
color:#666;
}
}
}
}

View file

@ -0,0 +1,30 @@
/** LISTS **/
ul {
/**
* List li block element #1
*
*/
.wll {
background-color: #FFF;
padding: 10px 5px;
min-height: 20px;
border-bottom: 1px solid #eee;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&.smoke { background-color:#f5f5f5; }
&:hover { background:$hover; }
&:last-child { border:none }
.author { color: #999; }
p {
padding-top:5px;
margin:0;
color:#222;
img {
position:relative;
top:3px;
}
}
}
}

View file

@ -0,0 +1,41 @@
table {
width:100%;
th {
padding-top: 9px;
font-weight: bold;
vertical-align: middle;
}
th, td {
padding: 10px 10px 9px;
line-height: 18px;
text-align: left;
}
&.bordered-table {
border: 1px solid #DDD;
border-collapse: separate;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
&.zebra-striped {
@extend .table-striped;
}
}
table.admin-table {
@extend .table-bordered;
@extend .zebra-striped;
@include solid_shade;
th {
border-color: #CCC;
border-bottom: 1px solid #bbb;
@include bg-gray-gradient;
}
}
table.no-borders {
border:none;
tr, td { border:none }
}

View file

@ -0,0 +1,71 @@
/**
* Headers
*
*/
h3, h4, h5, h6 { line-height: 36px; }
h5 { font-size:14px; }
h3.page_title {
color:#456;
font-size:20px;
font-weight: normal;
line-height: 28px;
}
/** CODE **/
pre {
font-family:'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
&.dark {
background: #333;
color:#f5f5f5;
}
}
/**
* Links
*
*/
a {
outline: none;
color: $link_color;
&:hover {
text-decoration:none;
color: $blue_link;
}
&.btn {
color: $style_color;
&:hover {
color: $style_color;
}
}
&.dark {
color: $style_color;
}
&.lined {
text-decoration:underline;
&:hover { text-decoration:underline; }
}
&.gray {
color:gray;
}
&.supp_diff_link {
text-align:center;
padding:20px 0;
background:#f1f1f1;
width:100%;
float:left;
}
&.neib {
margin-right:15px;
}
}
a:focus {
outline: none;
}

View file

@ -2,26 +2,10 @@
@import "bootstrap-responsive"; @import "bootstrap-responsive";
/** GITLAB colors **/ /** GITLAB colors **/
$text_color:#222; $link_color:#3A89A3;
$lite_text_color: #666;
$link_color:#2A79A3;
$active_link_color:#2FA0BB;
$active_bg_color:#79C3E0;
$active_bd_color: #2FA0BB;
$border_color:#CCC;
$lite_border_color:#EEE;
$min_app_width:980px;
$max_app_width:980px;
$app_padding:20px;
$bg_color: #FFF;
$styled_border_color: #2FA0BB;
$color: "#4BB8D2";
$blue_link: #2fa0bb; $blue_link: #2fa0bb;
$style_color: #474d57;
$hover: #fdf5d9;
/** Style colors **/
$style_color: #474D57;
$hover: #FDF5D9;
/** GITLAB Fonts **/ /** GITLAB Fonts **/
@font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); } @font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); }
@ -72,7 +56,20 @@ $hover: #FDF5D9;
border-radius: $radius; border-radius: $radius;
} }
@mixin bg-gray-gradient {
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
}
@mixin bg-dark-gray-gradient {
background:#eee;
background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
}
/** /**
* Header of application. * Header of application.
@ -113,7 +110,13 @@ $hover: #FDF5D9;
* Overrides some styles of twitter bootstrap. * Overrides some styles of twitter bootstrap.
* Also give some common classes for gitlab app * Also give some common classes for gitlab app
*/ */
@import "gitlab_bootstrap.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/tables.scss";
@import "gitlab_bootstrap/lists.scss";
/** /**

View file

@ -1,385 +0,0 @@
.git_url_wrapper { margin-right:50px }
.sidebar aside a{
display: block;
position: relative;
padding: 15px 10px;
margin: 10px 0 0 0;
font-size:13px;
font-weight:bold;
color:#333;
&.current {
color: white;
background: $active_bg_color;
border: 1px solid $active_bd_color;
border-radius:5px;
-webkit-border-top-right-radius: 0;
-webkit-border-bottom-right-radius: 0;
-moz-border-radius-topright: 0px;
-moz-border-radius-bottomright: 0px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin-right: -1px;
}
}
body table .commit a{color: #{$blue_link}}
body table th, body table td{ border-bottom: 1px solid #DEE2E3;}
body .fixed{position: fixed; }
/** File stat **/
.file_stats {
span {
img {
width:14px;
float:left;
margin-right: 6px;
padding:2px 0;
}
}
}
.round-borders {
@include round-borders-all(4px);
padding: 4px 0px;
}
table.round-borders {
float:left;
text-align: left;
}
/** PROJECTS **/
input.ssh_project_url {
padding:5px;
margin:0px;
float:right;
width:400px;
text-align:center;
}
#projects-list .project {
height:50px;
}
#tree-slider .tree-item,
#projects-list .project,
#snippets-table .snippet,
#issues-table .issue{
cursor:pointer;
}
.clear {
clear: both;
}
#user_projects_limit{
width: 60px;
}
.handle:hover{
cursor: move;
}
.project-refs-form {
span {
background: none !important;
position:static !important;
width:auto !important;
height: auto !important;
}
}
.project-refs-select {
width:200px;
}
.filter .left { margin-right:15px; }
body table .commit {
a.tree-commit-link {
color:#444;
&:hover {
text-decoration:underline;
}
}
}
/** NEW PROJECT **/
.new-project-hodler {
.icon span { background-position: -31px -70px; }
td { border-bottom: 1px solid #DEE2E3; }
}
/** Feed entry **/
.commit,
.snippet,
.message {
.title {
color:#666;
a { color:#666 !important; }
p { margin-top:0px; }
}
.author { color: #999 }
}
/** JQuery UI **/
.ui-autocomplete { @include round-borders-all(5px); }
.ui-menu-item { cursor: pointer }
.ui-selectmenu{
@include round-borders-all(4px);
margin-right:10px;
font-size:1.5em;
height:auto;
font-weight:bold;
.ui-selectmenu-status {
padding:3px 10px;
}
}
#holder {
background:#FAFAFA;
border: 1px solid #EEE;
cursor: move;
height: 70%;
overflow: hidden;
}
/* Project Dashboard Page */
html, body { height: 100%; }
.news-feed h2{float: left;}
.news-feed .project-updates {margin-bottom: 20px; display: block; width: 100%;}
.news-feed .project-updates .data{ padding: 0}
.news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
.news-feed .project-updates a.project-update:last-child{border-bottom: 0}
.news-feed .project-updates a.project-update img{float: left; margin-right: 10px;}
.news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;}
.news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px}
.news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;}
.news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;}
/* eo Dashboard Page */
/** Update entry **/
.update-data { padding: 0 }
.update-data { width:100%; }
.update-data.ui-box .data { padding:0; }
a.update-item {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;}
a.update-item:last-child{border-bottom: 0}
a.update-item img{float: left; margin-right: 10px;}
a.update-item span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;}
a.update-item span.update-title{margin-bottom: 10px}
a.update-item span.update-author{color: #999; font-weight: normal; font-style: italic;}
a.update-item span.update-author strong{font-weight: bold; font-style: normal;}
body .team_member_new .span-6, .team_member_edit .span-6{ padding:10px 0; }
body.projects-page input.text.git-url.project_list_url { width:165px; }
body table.no-borders th {
background:none;
border-bottom:1px solid #CCC;
color:#333;
}
body table.no-borders tr,
body table.no-borders td{
border:none;
}
.ajax-tab-loading {
padding:40px;
display:none;
}
#tree-content-holder { float:left; width:100%; }
#tree-readme-holder {
float:left;
width:100%;
.readme {
@include round-borders-all(4px);
padding: 4px 15px;
background:#F7F7F7;
}
}
/* Commit Page */
.entity-info {float: right;}
.entity-button{
background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4));
background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4);
background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4);
background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4);
box-shadow: 0 -1px 0 white inset;
display: block;
border: 1px solid #eee;
border-radius: 5px;
margin-bottom: 2px;
position: relative;
padding: 4px 10px;
font-size: 11px;
padding-right: 20px;
}
.entity-button i{
background: url('images.png') no-repeat -138px -27px;
width: 6px;
height: 9px;
float: right;
position: absolute;
top: 6px;
right: 5px;
}
.box-arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999; margin: 1.5em 0;}
h4.dash-tabs {
margin: 0;
border-bottom: 1px solid #ccc;
padding: 10px 10px;
font-size: 11px;
padding-left:20px;
font-weight: bold; text-transform: uppercase;
background: #F7F7F7;
margin-bottom:20px;
height:13px;
}
.dash-button {
border-right: 1px solid #ddd;
background:none;
padding: 10px 15px;
float:left;
position:relative;
top:-10px;
left:0px;
height:13px;
&:first-child {
border-left: 1px solid #ddd;
}
&.active {
background: #eaeaea;
}
}
.dashboard-loader {
float:right;
margin-right:30px;
display:none;
}
.merge-tabs {
margin: 0;
border: 1px solid #ccc;
padding: 5px;
font-size: 12px;
background: #F7F7F7;
margin-bottom:20px;
height:26px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
.tab {
font-weight: bold;
border-right: 1px solid #ddd;
background:none;
padding: 10px;
min-width:60px;
float:left;
position:relative;
top:-5px;
left:-5px;
height:16px;
padding-left:34px;
span {
width: 20px;
height: 20px;
display: inline-block;
position: absolute;
left: 8px;
top: 8px;
}
&.active {
background: #eaeaea;
}
}
}
.merge-tabs.repository .tab span{ background: url("images.png") no-repeat -38px -77px; }
.activities-tab span { background: url("images.png") no-repeat -161px -1px; }
.stat-tab span,
.team-tab span,
.snippets-tab span { background: url("images.png") no-repeat -38px -77px; }
.files-tab span { background: url("images.png") no-repeat -112px -23px; }
.merge-notes-tab span { background: url("images.png") no-repeat -161px -1px; }
.merge-commits-tab span { background: url("images.png") no-repeat -86px 1px; }
.merge-diffs-tab span { background: url("images.png") no-repeat -118px 1px; }
.merge-tabs .dashboard-loader { padding:8px; }
.user-mention {
color: #2FA0BB;
font-weight: bold;
}
.author {
color: #999;
}
.dark_scheme_box {
padding:20px 0;
label {
float:left;
box-shadow: 0 0px 5px rgba(0,0,0,.3);
img {
}
}
}
a.project-update.titled {
position: relative;
padding-left: 235px !important;
.title-block {
padding: 10px;
width: 205px;
position: absolute;
left: 0;
top: 0;
}
}
.add_new {
float: right;
background: #A6B807;
color: white;
padding: 4px 10px;
@include round-borders-all(4px);
font-size:11px;
margin: 10px 0;
}

View file

@ -33,9 +33,7 @@
} }
.chzn-single { .chzn-single {
background:#ddd; @include bg-gray-gradient;
//border:none;
//box-shadow:none;
div { div {
background:transparent; background:transparent;

View file

@ -206,4 +206,24 @@
min-width:65px; min-width:65px;
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace; font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
} }
.commit-author-name {
color: #777;
}
}
.diff_file_header a,
.file_stats a {
color:$style_color;
}
.file_stats {
span {
img {
width:14px;
float:left;
margin-right:6px;
padding:2px 0;
}
}
} }

View file

@ -6,11 +6,7 @@
h4 { h4 {
padding:0 10px; padding:0 10px;
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
background:#eee; @include bg-gray-gradient;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
} }
.graph { .graph {

View file

@ -65,6 +65,11 @@ input.check_all_issues {
} }
} }
@media (min-width: 800px) { .issues_filters select { width:160px; } }
@media (min-width: 1000px) { .issues_filters select { width:200px; } }
@media (min-width: 1200px) { .issues_filters select { width:220px; } }
#issues-table-holder { #issues-table-holder {
.issues_filters { .issues_filters {
form { form {
@ -99,3 +104,11 @@ input.check_all_issues {
#update_status { #update_status {
width:100px; width:100px;
} }
/**
* Milestones list
*
*/
.milestone {
@extend .wll;
}

View file

@ -11,23 +11,6 @@
background:#f1f1f1; background:#f1f1f1;
} }
.commit {
margin:0;
padding:0;
padding: 5px;
margin-bottom: 5px;
.committed_ago {
display:none;
}
.browse_code_link_holder {
display:none;
}
list-style:none;
&:hover {
background:none;
}
}
} }
/** /**
@ -55,6 +38,7 @@
background: #CEB; background: #CEB;
.accept_merge_request { .accept_merge_request {
font-size:13px;
float:left; float:left;
} }
.remove_branch_holder { .remove_branch_holder {
@ -99,3 +83,42 @@ li.merge_request {
@extend .padded; @extend .padded;
@extend .append-bottom-10; @extend .append-bottom-10;
} }
.label_branch {
@include round-borders-all(4px);
padding:2px 4px;
border:none;
font-size:13px;
background: #474D57;
color:#fff;
font-weight:bold;
font-family: monospace;
}
.mr_source_commit,
.mr_target_commit {
.commit {
margin:0;
padding:0;
padding: 5px;
margin-bottom: 5px;
.avatar { position:relative }
.row_title {
color:#444;
}
.commit-author-name,
.dash,
.committed_ago,
.browse_code_link_holder {
display:none;
}
list-style:none;
&:hover {
background:none;
}
}
}
.mr_direction_tip {
margin-top:40px
}

View file

@ -6,13 +6,9 @@ ul.main_menu {
border-radius: 4px; border-radius: 4px;
margin: auto; margin: auto;
margin:30px 0; margin:30px 0;
background:#eee; border:1px solid #AAA;
border:1px solid #bbb;
height:37px; height:37px;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); @include bg-gray-gradient;
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
position:relative; position:relative;
overflow:hidden; overflow:hidden;
@include shade; @include shade;
@ -89,7 +85,7 @@ ul.main_menu {
line-height:36px; line-height:36px;
color: $style_color; color: $style_color;
text-shadow:0 1px 1px white; text-shadow:0 1px 1px white;
padding:0 10px;
} }
} }
/* /*

View file

@ -30,14 +30,22 @@
} }
#new_note { #new_note {
#note_note { .note-text {
height:25px; height:40px;
} }
.attach_holder { .attach_holder {
display:none; display:none;
} }
} }
.preview_note {
margin: 2px;
border: 1px solid #ddd;
padding: 10px;
min-height: 60px;
background:#f5f5f5;
}
.note { .note {
padding: 8px 0; padding: 8px 0;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
@ -204,3 +212,8 @@ td .line_note_link {
} }
} }
} }
.note-text {
border: 1px solid #aaa;
box-shadow:none;
}

View file

@ -12,6 +12,33 @@
color:$style_color; color:$style_color;
font-size:16px; font-size:16px;
text-shadow: 0 1px 1px #fff; text-shadow: 0 1px 1px #fff;
padding: 2px 10px;
}
ul {
li {
padding:0;
a {
display:block;
.project_name {
color:#4fa2bd;
font-size:14px;
line-height:18px;
}
.arrow {
float:right;
padding:10px;
margin:0;
}
.last_activity {
padding-top:5px;
display:block;
span, strong {
font-size:12px;
color:#666;
}
}
}
}
} }
@extend .leftbar; @extend .leftbar;
@extend .ui-box; @extend .ui-box;
@ -32,8 +59,34 @@
color:#888; color:#888;
} }
.btn { .btn {
padding:6px; padding:6px 10px;
margin-left:10px; margin-left:10px;
margin-bottom:8px;
} }
} }
.adv_settings {
h6 { margin-left:40px; }
}
}
.project_clone_panel {
@include border-radius(4px);
@include bg-gray-gradient;
padding: 4px 7px;
border: 1px solid #CCC;
margin-bottom:5px;
input[type=text] {
border: 1px solid #BBB;
}
}
.save-project-loader {
img {
margin-top:50px;
margin-bottom:50px;
}
h3 {
@extend .page_title;
}
} }

View file

@ -72,11 +72,7 @@
th { th {
border-color: #CCC; border-color: #CCC;
border-bottom: 1px solid #bbb; border-bottom: 1px solid #bbb;
background:#eee; @include bg-gray-gradient;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
} }
} }

View file

@ -20,6 +20,10 @@
.fbtn { .fbtn {
.btn { .btn {
i {
position: relative;
top: 1px;
}
margin-left:8px; margin-left:8px;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595D63), to(#31363E)); background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595D63), to(#31363E));
background-image: -webkit-linear-gradient(#595D63 6.6%, #31363E); background-image: -webkit-linear-gradient(#595D63 6.6%, #31363E);
@ -32,6 +36,10 @@
background-image: -moz-linear-gradient(#595D63 6.6%, #202227); background-image: -moz-linear-gradient(#595D63 6.6%, #202227);
background-image: -o-linear-gradient(#595D63 6.6%, #202227); background-image: -o-linear-gradient(#595D63 6.6%, #202227);
background-position:0 0; background-position:0 0;
color:#fff;
i {
@extend .icon-white;
}
} }
border: 1px solid #31363E; border: 1px solid #31363E;

View file

@ -1,13 +1,13 @@
class MergeRequestsLoad < BaseContext class MergeRequestsLoad < BaseContext
def execute def execute
type = params[:f].to_i type = params[:f]
merge_requests = project.merge_requests merge_requests = project.merge_requests
merge_requests = case type merge_requests = case type
when 1 then merge_requests when 'all' then merge_requests
when 2 then merge_requests.closed when 'closed' then merge_requests.closed
when 3 then merge_requests.opened.assigned(current_user) when 'assigned-to-me' then merge_requests.opened.assigned(current_user)
else merge_requests.opened else merge_requests.opened
end.page(params[:page]).per(20) end.page(params[:page]).per(20)

View file

@ -14,6 +14,10 @@ class ApplicationController < ActionController::Base
render "errors/gitolite", layout: "error" render "errors/gitolite", layout: "error"
end end
rescue_from Gitlab::Gitolite::InvalidKey do |exception|
render "errors/invalid_ssh_key", layout: "error"
end
rescue_from Encoding::CompatibilityError do |exception| rescue_from Encoding::CompatibilityError do |exception|
render "errors/encoding", layout: "error", status: 404 render "errors/encoding", layout: "error", status: 404
end end

View file

@ -60,7 +60,13 @@ class IssuesController < ApplicationController
@issue.save @issue.save
respond_to do |format| respond_to do |format|
format.html { redirect_to project_issue_path(@project, @issue) } format.html do
if @issue.valid?
redirect_to project_issue_path(@project, @issue)
else
render :new
end
end
format.js format.js
end end
end end
@ -162,10 +168,10 @@ class IssuesController < ApplicationController
def issues_filter def issues_filter
{ {
all: "1", all: "all",
closed: "2", closed: "closed",
to_me: "3", to_me: "assigned-to-me",
open: "0" open: "open"
} }
end end
end end

View file

@ -0,0 +1,25 @@
class LabelsController < ApplicationController
before_filter :authenticate_user!
before_filter :project
before_filter :module_enabled
layout "project"
# Authorize
before_filter :add_project_abilities
# Allow read any issue
before_filter :authorize_read_issue!
respond_to :js, :html
def index
@labels = @project.issues.tag_counts_on(:labels).order('count DESC')
end
protected
def module_enabled
return render_404 unless @project.issues_enabled
end
end

View file

@ -103,10 +103,12 @@ class MergeRequestsController < ApplicationController
def branch_from def branch_from
@commit = project.commit(params[:ref]) @commit = project.commit(params[:ref])
@commit = CommitDecorator.decorate(@commit)
end end
def branch_to def branch_to
@commit = project.commit(params[:ref]) @commit = project.commit(params[:ref])
@commit = CommitDecorator.decorate(@commit)
end end
protected protected

View file

@ -17,8 +17,8 @@ class MilestonesController < ApplicationController
respond_to :html respond_to :html
def index def index
@milestones = case params[:f].to_i @milestones = case params[:f]
when 1; @project.milestones when 'all'; @project.milestones
else @project.milestones.active else @project.milestones.active
end end

View file

@ -12,8 +12,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def ldap def ldap
# We only find ourselves here if the authentication to LDAP was successful. # We only find ourselves here if the authentication to LDAP was successful.
info = request.env["omniauth.auth"]["info"] @user = User.find_for_ldap_auth(request.env["omniauth.auth"], current_user)
@user = User.find_for_ldap_auth(info)
if @user.persisted? if @user.persisted?
@user.remember_me = true @user.remember_me = true
end end

View file

@ -9,6 +9,7 @@ class TeamMembersController < ApplicationController
def show def show
@team_member = project.users_projects.find(params[:id]) @team_member = project.users_projects.find(params[:id])
@events = @team_member.user.recent_events.where(:project_id => @project.id).limit(7)
end end
def new def new

View file

@ -1,4 +1,4 @@
class ApplicationDecorator < Drapper::Base class ApplicationDecorator < Draper::Base
# Lazy Helpers # Lazy Helpers
# PRO: Call Rails helpers without the h. proxy # PRO: Call Rails helpers without the h. proxy
# ex: number_to_currency(model.price) # ex: number_to_currency(model.price)

View file

@ -2,10 +2,13 @@ require 'digest/md5'
module ApplicationHelper module ApplicationHelper
def gravatar_icon(user_email = '', size = 40) def gravatar_icon(user_email = '', size = 40)
return unless user_email if Gitlab.config.disable_gravatar? || user_email.blank?
gravatar_host = request.ssl? ? "https://secure.gravatar.com" : "http://www.gravatar.com" 'no_avatar.png'
else
gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
user_email.strip! user_email.strip!
"#{gravatar_host}/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=identicon"
end
end end
def request_protocol def request_protocol
@ -123,4 +126,13 @@ module ApplicationHelper
def hexdigest(string) def hexdigest(string)
Digest::SHA1.hexdigest string Digest::SHA1.hexdigest string
end end
def project_last_activity project
activity = project.last_activity
if activity && activity.created_at
time_ago_in_words(activity.created_at) + " ago"
else
"Never"
end
end
end end

View file

@ -1,9 +1,18 @@
module GitlabMarkdownHelper module GitlabMarkdownHelper
# Replaces references (i.e. @abc, #123, !456, ...) in the text with links to
# the appropriate items in Gitlab.
#
# text - the source text
# html_options - extra options for the reference links as given to link_to
#
# note: reference links will only be generated if @project is set
#
# see Gitlab::Markdown for details on the supported syntax
def gfm(text, html_options = {}) def gfm(text, html_options = {})
return text if text.nil? return text if text.nil?
return text if @project.nil? return text if @project.nil?
# Extract pre blocks # Extract pre blocks so they are not altered
# from http://github.github.com/github-flavored-markdown/ # from http://github.github.com/github-flavored-markdown/
extractions = {} extractions = {}
text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match| text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
@ -22,10 +31,18 @@ module GitlabMarkdownHelper
extractions[$1] extractions[$1]
end end
text.html_safe sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class )
end end
# circumvents nesting links, which will behave bad in browsers # Use this in places where you would normally use link_to(gfm(...), ...).
#
# It solves a problem occurring with nested links (i.e.
# "<a>outer text <a>gfm ref</a> more outer text</a>"). This will not be
# interpreted as intended. Browsers will parse something like
# "<a>outer text </a><a>gfm ref</a> more outer text" (notice the last part is
# not linked any more). link_to_gfm corrects that. It wraps all parts to
# explicitly produce the correct linking behavior (i.e.
# "<a>outer text </a><a>gfm ref</a><a> more outer text</a>").
def link_to_gfm(body, url, html_options = {}) def link_to_gfm(body, url, html_options = {})
gfm_body = gfm(body, html_options) gfm_body = gfm(body, html_options)
@ -37,7 +54,14 @@ module GitlabMarkdownHelper
end end
def markdown(text) def markdown(text)
@__renderer ||= Redcarpet::Markdown.new(Redcarpet::Render::GitlabHTML.new(self, filter_html: true, with_toc_data: true), { unless @markdown
gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self,
# see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch-
filter_html: true,
with_toc_data: true,
hard_wrap: true)
@markdown ||= Redcarpet::Markdown.new(gitlab_renderer,
# see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
no_intra_emphasis: true, no_intra_emphasis: true,
tables: true, tables: true,
fenced_code_blocks: true, fenced_code_blocks: true,
@ -45,9 +69,9 @@ module GitlabMarkdownHelper
strikethrough: true, strikethrough: true,
lax_html_blocks: true, lax_html_blocks: true,
space_after_headers: true, space_after_headers: true,
superscript: true superscript: true)
}) end
@__renderer.render(text).html_safe @markdown.render(text).html_safe
end end
end end

View file

@ -12,74 +12,117 @@ class Notify < ActionMailer::Base
def new_user_email(user_id, password) def new_user_email(user_id, password)
@user = User.find(user_id) @user = User.find(user_id)
@password = password @password = password
mail(to: @user.email, subject: "gitlab | Account was created for you") mail(to: @user.email, subject: subject("Account was created for you"))
end end
def new_issue_email(issue_id) def new_issue_email(issue_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@project = @issue.project @project = @issue.project
mail(to: @issue.assignee_email, subject: "gitlab | new issue ##{@issue.id} | #{@issue.title} | #{@project.name}") mail(to: @issue.assignee_email, subject: subject("new issue ##{@issue.id}", @issue.title))
end end
def note_wall_email(recipient_id, note_id) def note_wall_email(recipient_id, note_id)
recipient = User.find(recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@project = @note.project @project = @note.project
mail(to: recipient.email, subject: "gitlab | #{@project.name}") mail(to: recipient(recipient_id), subject: subject)
end end
def note_commit_email(recipient_id, note_id) def note_commit_email(recipient_id, note_id)
recipient = User.find(recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@commit = @note.target @commit = @note.target
@commit = CommitDecorator.decorate(@commit) @commit = CommitDecorator.decorate(@commit)
@project = @note.project @project = @note.project
mail(to: recipient.email, subject: "gitlab | note for commit #{@commit.short_id} | #{@commit.title} | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
end end
def note_merge_request_email(recipient_id, note_id) def note_merge_request_email(recipient_id, note_id)
recipient = User.find(recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@merge_request = @note.noteable @merge_request = @note.noteable
@project = @note.project @project = @note.project
mail(to: recipient.email, subject: "gitlab | note for merge request !#{@merge_request.id} | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("note for merge request !#{@merge_request.id}"))
end end
def note_issue_email(recipient_id, note_id) def note_issue_email(recipient_id, note_id)
recipient = User.find(recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@issue = @note.noteable @issue = @note.noteable
@project = @note.project @project = @note.project
mail(to: recipient.email, subject: "gitlab | note for issue ##{@issue.id} | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("note for issue ##{@issue.id}"))
end end
def note_wiki_email(recipient_id, note_id) def note_wiki_email(recipient_id, note_id)
recipient = User.find(recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@wiki = @note.noteable @wiki = @note.noteable
@project = @note.project @project = @note.project
mail(to: recipient.email, subject: "gitlab | note for wiki | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("note for wiki"))
end end
def new_merge_request_email(merge_request_id) def new_merge_request_email(merge_request_id)
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project @project = @merge_request.project
mail(to: @merge_request.assignee_email, subject: "gitlab | new merge request !#{@merge_request.id} | #{@merge_request.title} | #{@project.name}") mail(to: @merge_request.assignee_email, subject: subject("new merge request !#{@merge_request.id}", @merge_request.title))
end end
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
recipient = User.find(recipient_id)
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@previous_assignee ||= User.find(previous_assignee_id) @previous_assignee ||= User.find(previous_assignee_id)
@project = @merge_request.project @project = @merge_request.project
mail(to: recipient.email, subject: "gitlab | changed merge request !#{@merge_request.id} | #{@merge_request.title} | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("changed merge request !#{@merge_request.id}", @merge_request.title))
end end
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
recipient = User.find(recipient_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@previous_assignee ||= User.find(previous_assignee_id) @previous_assignee ||= User.find(previous_assignee_id)
@project = @issue.project @project = @issue.project
mail(to: recipient.email, subject: "gitlab | changed issue ##{@issue.id} | #{@issue.title} | #{@project.name}") mail(to: recipient(recipient_id), subject: subject("changed issue ##{@issue.id}", @issue.title))
end
def project_access_granted_email(user_project_id)
@users_project = UsersProject.find user_project_id
@project = @users_project.project
mail(to: @users_project.user.email,
subject: subject("access to project was granted"))
end
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
@issue = Issue.find issue_id
@issue_status = status
@updated_by = User.find updated_by_user_id
mail(to: recipient(recipient_id),
subject: subject("changed issue ##{@issue.id}", @issue.title))
end
private
# Look up a User by their ID and return their email address
#
# recipient_id - User ID
#
# Returns a String containing the User's email address.
def recipient(recipient_id)
if recipient = User.find(recipient_id)
recipient.email
end
end
# Formats arguments into a String suitable for use as an email subject
#
# extra - Extra Strings to be inserted into the subject
#
# Examples
#
# >> subject('Lorem ipsum')
# => "gitlab | Lorem ipsum"
#
# # Automatically inserts Project name when @project is set
# >> @project = Project.last
# => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...>
# >> subject('Lorem ipsum')
# => "gitlab | Lorem ipsum | Ruby on Rails"
#
# # Accepts multiple arguments
# >> subject('Lorem ipsum', 'Dolor sit amet')
# => "gitlab | Lorem ipsum | Dolor sit amet"
def subject(*extra)
"gitlab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
end end
end end

View file

@ -1,16 +1,18 @@
require 'digest/md5' require 'digest/md5'
class Key < ActiveRecord::Base class Key < ActiveRecord::Base
include SshKey
belongs_to :user belongs_to :user
belongs_to :project belongs_to :project
attr_protected :user_id
validates :title, validates :title,
presence: true, presence: true,
length: { within: 0..255 } length: { within: 0..255 }
validates :key, validates :key,
presence: true, presence: true,
format: { :with => /ssh-.{3} / },
length: { within: 0..5000 } length: { within: 0..5000 }
before_save :set_identifier before_save :set_identifier
@ -50,6 +52,10 @@ class Key < ActiveRecord::Base
user.projects user.projects
end end
end end
def last_deploy?
Key.where(identifier: identifier).count == 0
end
end end
# == Schema Information # == Schema Information
# #

View file

@ -88,8 +88,11 @@ class MergeRequest < ActiveRecord::Base
end end
def unmerged_diffs def unmerged_diffs
commits = project.repo.commits_between(target_branch, source_branch).map {|c| Commit.new(c)} # Only show what is new in the source branch compared to the target branch, not the other way around.
diffs = project.repo.diff(commits.first.prev_commit.id, commits.last.id) rescue [] # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
# From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
common_commit = project.repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip
diffs = project.repo.diff(common_commit, source_branch)
end end
def last_commit def last_commit

View file

@ -28,18 +28,10 @@ class Milestone < ActiveRecord::Base
end end
def percent_complete def percent_complete
@percent_complete ||= begin ((self.issues.closed.count * 100) / self.issues.count).abs
total_i = self.issues.count rescue ZeroDivisionError
closed_i = self.issues.closed.count
if total_i > 0
(closed_i * 100) / total_i
else
100 100
end end
rescue => ex
0
end
end
def expires_at def expires_at
"expires at #{due_date.stamp("Aug 21, 2011")}" if due_date "expires at #{due_date.stamp("Aug 21, 2011")}" if due_date

View file

@ -2,7 +2,7 @@ require "grit"
class Project < ActiveRecord::Base class Project < ActiveRecord::Base
include Repository include Repository
include ProjectPush include PushObserver
include Authority include Authority
include Team include Team
@ -158,7 +158,7 @@ class Project < ActiveRecord::Base
end end
def last_activity def last_activity
events.last || nil events.order("created_at ASC").last
end end
def last_activity_date def last_activity_date

View file

@ -1,4 +1,6 @@
class ProtectedBranch < ActiveRecord::Base class ProtectedBranch < ActiveRecord::Base
include GitHost
belongs_to :project belongs_to :project
validates_presence_of :project_id validates_presence_of :project_id
validates_presence_of :name validates_presence_of :name
@ -7,7 +9,7 @@ class ProtectedBranch < ActiveRecord::Base
after_destroy :update_repository after_destroy :update_repository
def update_repository def update_repository
Gitlab::GitHost.system.update_project(project.path, project) git_host.update_repository(project)
end end
def commit def commit

View file

@ -7,7 +7,7 @@ class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, attr_accessible :email, :password, :password_confirmation, :remember_me, :bio,
:name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme, :name, :projects_limit, :skype, :linkedin, :twitter, :dark_scheme,
:theme_id, :force_random_password :theme_id, :force_random_password, :extern_uid, :provider
attr_accessor :force_random_password attr_accessor :force_random_password
@ -54,6 +54,8 @@ class User < ActiveRecord::Base
validates :bio, length: { within: 0..255 } validates :bio, length: { within: 0..255 }
validates :extern_uid, :allow_blank => true, :uniqueness => {:scope => :provider}
before_save :ensure_authentication_token before_save :ensure_authentication_token
alias_attribute :private_token, :authentication_token alias_attribute :private_token, :authentication_token
@ -84,21 +86,31 @@ class User < ActiveRecord::Base
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)') where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
end end
def self.find_for_ldap_auth(omniauth_info) def self.find_for_ldap_auth(auth, signed_in_resource=nil)
name = omniauth_info.name.force_encoding("utf-8") uid = auth.info.uid
email = omniauth_info.email.downcase unless omniauth_info.email.nil? provider = auth.provider
raise OmniAuth::Error, "LDAP accounts must provide an email address" if email.nil? name = auth.info.name.force_encoding("utf-8")
email = auth.info.email.downcase unless auth.info.email.nil?
raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
if @user = User.find_by_email(email) if @user = User.find_by_extern_uid_and_provider(uid, provider)
@user
# workaround for backward compatibility
elsif @user = User.find_by_email(email)
logger.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
@user.update_attributes(:extern_uid => uid, :provider => provider)
@user @user
else else
logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
password = Devise.friendly_token[0, 8].downcase password = Devise.friendly_token[0, 8].downcase
@user = User.create( @user = User.create(
name: name, :extern_uid => uid,
email: email, :provider => provider,
password: password, :name => name,
password_confirmation: password, :email => email,
projects_limit: Gitlab.config.default_projects_limit :password => password,
:password_confirmation => password,
:projects_limit => Gitlab.config.default_projects_limit
) )
end end
end end

View file

@ -1,4 +1,6 @@
class UsersProject < ActiveRecord::Base class UsersProject < ActiveRecord::Base
include GitHost
GUEST = 10 GUEST = 10
REPORTER = 20 REPORTER = 20
DEVELOPER = 30 DEVELOPER = 30
@ -58,9 +60,7 @@ class UsersProject < ActiveRecord::Base
end end
def update_repository def update_repository
Gitlab::GitHost.system.new.configure do |c| git_host.update_repository(project)
c.update_project(project.path, project)
end
end end
def project_access_human def project_access_human

View file

@ -9,8 +9,16 @@ class IssueObserver < ActiveRecord::Observer
def after_update(issue) def after_update(issue)
send_reassigned_email(issue) if issue.is_being_reassigned? send_reassigned_email(issue) if issue.is_being_reassigned?
Note.create_status_change_note(issue, current_user, 'closed') if issue.is_being_closed?
Note.create_status_change_note(issue, current_user, 'reopened') if issue.is_being_reopened? status = nil
status = 'closed' if issue.is_being_closed?
status = 'reopened' if issue.is_being_reopened?
if status
Note.create_status_change_note(issue, current_user, status)
[issue.author, issue.assignee].compact.each do |recipient|
Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user)
end
end
end end
protected protected

View file

@ -1,9 +1,12 @@
class KeyObserver < ActiveRecord::Observer class KeyObserver < ActiveRecord::Observer
include GitHost
def after_save(key) def after_save(key)
key.update_repository git_host.set_key(key.identifier, key.key, key.projects)
end end
def after_destroy(key) def after_destroy(key)
key.repository_delete_key return if key.is_deploy_key && !key.last_deploy?
git_host.remove_key(key.identifier, key.projects)
end end
end end

View file

@ -0,0 +1,9 @@
class UsersProjectObserver < ActiveRecord::Observer
def after_create(users_project)
Notify.project_access_granted_email(users_project.id).deliver
end
def after_update(users_project)
Notify.project_access_granted_email(users_project.id).deliver
end
end

5
app/roles/git_host.rb Normal file
View file

@ -0,0 +1,5 @@
module GitHost
def git_host
Gitlab::Gitolite.new
end
end

View file

@ -1,2 +0,0 @@
module GitMerge
end

View file

@ -1,4 +1,4 @@
module ProjectPush module PushObserver
def observe_push(oldrev, newrev, ref, user) def observe_push(oldrev, newrev, ref, user)
data = post_receive_data(oldrev, newrev, ref, user) data = post_receive_data(oldrev, newrev, ref, user)

View file

@ -1,4 +1,6 @@
module Repository module Repository
include GitHost
def valid_repo? def valid_repo?
repo repo
rescue rescue
@ -30,26 +32,10 @@ module Repository
Commit.commits_between(repo, from, to) Commit.commits_between(repo, from, to)
end end
def write_hooks
%w(post-receive).each do |hook|
write_hook(hook, File.read(File.join(Rails.root, 'lib', "#{hook}-hook")))
end
end
def satellite def satellite
@satellite ||= Gitlab::Satellite.new(self) @satellite ||= Gitlab::Satellite.new(self)
end end
def write_hook(name, content)
hook_file = File.join(path_to_repo, 'hooks', name)
File.open(hook_file, 'w') do |f|
f.write(content)
end
File.chmod(0775, hook_file)
end
def has_post_receive_file? def has_post_receive_file?
hook_file = File.join(path_to_repo, 'hooks', 'post-receive') hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
File.exists?(hook_file) File.exists?(hook_file)
@ -64,7 +50,7 @@ module Repository
end end
def url_to_repo def url_to_repo
Gitlab::GitHost.url_to_repo(path) git_host.url_to_repo(path)
end end
def path_to_repo def path_to_repo
@ -72,13 +58,11 @@ module Repository
end end
def update_repository def update_repository
Gitlab::GitHost.system.update_project(path, self) git_host.update_repository(self)
write_hooks if File.exists?(path_to_repo)
end end
def destroy_repository def destroy_repository
Gitlab::GitHost.system.destroy_project(self) git_host.remove_repository(self)
end end
def repo_exists? def repo_exists?
@ -133,10 +117,13 @@ module Repository
storage_path = File.join(Rails.root, "tmp", "repositories", self.code) storage_path = File.join(Rails.root, "tmp", "repositories", self.code)
file_path = File.join(storage_path, file_name) file_path = File.join(storage_path, file_name)
# Put files into a directory before archiving
prefix = self.code + "/"
# Create file if not exists # Create file if not exists
unless File.exists?(file_path) unless File.exists?(file_path)
FileUtils.mkdir_p storage_path FileUtils.mkdir_p storage_path
file = self.repo.archive_to_file(ref, nil, file_path) file = self.repo.archive_to_file(ref, prefix, file_path)
end end
file_path file_path

View file

@ -1,18 +0,0 @@
module SshKey
def update_repository
Gitlab::GitHost.system.new.configure do |c|
c.update_keys(identifier, key)
c.update_projects(projects)
end
end
def repository_delete_key
Gitlab::GitHost.system.new.configure do |c|
#delete key file is there is no identically deploy keys
if !is_deploy_key || Key.where(identifier: identifier).count() == 0
c.delete_key(identifier)
end
c.update_projects(projects)
end
end
end

View file

@ -35,11 +35,13 @@
%h3 Latest projects %h3 Latest projects
%hr %hr
- @projects.each do |project| - @projects.each do |project|
%h5 %p
= link_to project.name, [:admin, project] = link_to project.name, [:admin, project]
.span6 .span6
%h3 Latest users %h3 Latest users
%hr %hr
- @users.each do |user| - @users.each do |user|
%h5 %p
= link_to user.name, [:admin, user] = link_to [:admin, user] do
= user.name
%small= user.email

View file

@ -5,7 +5,7 @@
Read more about system hooks Read more about system hooks
%strong #{link_to "here", help_system_hooks_path, class: "vlink"} %strong #{link_to "here", help_system_hooks_path, class: "vlink"}
= form_for @hook, as: :hook, url: admin_hooks_path do |f| = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-inline' } do |f|
-if @hook.errors.any? -if @hook.errors.any?
.alert-message.block-message.error .alert-message.block-message.error
- @hook.errors.full_messages.each do |msg| - @hook.errors.full_messages.each do |msg|

View file

@ -10,19 +10,17 @@
Project name is Project name is
.input .input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge" = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
= f.submit project.new_record? ? 'Create project' : 'Save Project', class: "btn primary"
%hr %hr
.alert.alert-info .adv_settings
%h5 Advanced settings: %h6 Advanced settings:
.clearfix .clearfix
= f.label :path do = f.label :path do
Git Clone Path
.input .input
.input-prepend .input-prepend
%span.add-on= Gitlab.config.ssh_path %strong
= f.text_field :path, placeholder: "example_project", disabled: !!project.id = text_field_tag :ppath, @admin_project.path_to_repo, class: "xlarge", disabled: true
%span.add-on= ".git"
.clearfix .clearfix
= f.label :code do = f.label :code do
URL URL
@ -42,8 +40,9 @@
.input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;") .input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
- unless project.new_record? - unless project.new_record?
.alert.alert-info %hr
%h5 Features: .adv_settings
%h6 Features:
.clearfix .clearfix
= f.label :issues_enabled, "Issues" = f.label :issues_enabled, "Issues"
@ -63,7 +62,8 @@
- unless project.new_record? - unless project.new_record?
.actions .actions
= f.submit 'Save Project', class: "btn primary" = f.submit 'Save Project', class: "btn save-btn"
= link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"

View file

@ -0,0 +1,29 @@
= form_for [:admin, @admin_project] do |f|
- if @admin_project.errors.any?
.alert-message.block-message.error
%span= @admin_project.errors.full_messages.first
.clearfix.project_name_holder
= f.label :name do
Project name is
.input
= f.text_field :name, placeholder: "Example Project", class: "xxlarge"
= f.submit 'Create project', class: "btn primary project-submit"
%hr
%div.adv_settings
%h6 Advanced settings:
.clearfix
= f.label :path do
Git Clone
.input
.input-prepend
%span.add-on= Gitlab.config.ssh_path
= f.text_field :path, placeholder: "example_project", disabled: !@admin_project.new_record?
%span.add-on= ".git"
.clearfix
= f.label :code do
URL
.input
.input-prepend
%span.add-on= web_app_url
= f.text_field :code, placeholder: "example"

View file

@ -1,8 +1,8 @@
%h3 %h3.page_title
Projects Projects
= link_to 'New Project', new_admin_project_path, class: "btn small right" = link_to 'New Project', new_admin_project_path, class: "btn small right"
%br %br
= form_tag admin_projects_path, method: :get do = form_tag admin_projects_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "xlarge" = text_field_tag :name, params[:name], class: "xlarge"
= submit_tag "Search", class: "btn submit primary" = submit_tag "Search", class: "btn submit primary"

View file

@ -1,3 +1,12 @@
%h3.page_title New project .project_new_holder
%hr %h3.page_title
= render 'form', project: @admin_project New Project
%hr
= render 'new_form'
%div.save-project-loader.hide
%center
= image_tag "ajax_loader.gif"
%h3 Creating project &amp; repository. Please wait a few minutes
:javascript
$(function(){ new Projects(); });

View file

@ -2,12 +2,14 @@
= form_for [:admin, @admin_user] do |f| = form_for [:admin, @admin_user] do |f|
-if @admin_user.errors.any? -if @admin_user.errors.any?
#error_explanation #error_explanation
%ul %ul.unstyled.alert.alert-error
- @admin_user.errors.full_messages.each do |msg| - @admin_user.errors.full_messages.each do |msg|
%li= msg %li= msg
.row .row
.span6 .span7
.ui-box
%br
.clearfix .clearfix
= f.label :name = f.label :name
.input .input
@ -19,12 +21,11 @@
= f.text_field :email = f.text_field :email
%span.help-inline * required %span.help-inline * required
%hr %hr
-if f.object.new_record? -if f.object.new_record?
.clearfix .clearfix
= f.label :admin, class: "checkbox" do = f.label :force_random_password do
= f.check_box :force_random_password, {}, true, nil
%span Generate random password %span Generate random password
.input= f.check_box :force_random_password, {}, true, nil
%div.password-fields %div.password-fields
.clearfix .clearfix
@ -43,30 +44,37 @@
.clearfix .clearfix
= f.label :twitter = f.label :twitter
.input= f.text_field :twitter .input= f.text_field :twitter
.span6 .span5
.ui-box
%br
.clearfix .clearfix
= f.label :projects_limit = f.label :projects_limit
.input= f.text_field :projects_limit, class: "small_input" .input= f.number_field :projects_limit
.alert
.clearfix .clearfix
%p Make the user a GitLab administrator. = f.label :admin do
= f.label :admin, class: "checkbox" do %strong.cred Administrator
= f.check_box :admin .input= f.check_box :admin
%span Administrator
- unless @admin_user.new_record? - unless @admin_user.new_record?
.alert.alert-error %hr
.padded.cred
- if @admin_user.blocked - if @admin_user.blocked
%span %span
= link_to 'Unblock', unblock_admin_user_path(@admin_user), method: :put, class: "btn small"
This user is blocked and is not able to login to GitLab This user is blocked and is not able to login to GitLab
.clearfix
= link_to 'Unblock User', unblock_admin_user_path(@admin_user), method: :put, class: "btn small right"
- else - else
%span %span
= link_to 'Block', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
Blocked users will be removed from all projects &amp; will not be able to login to GitLab. Blocked users will be removed from all projects &amp; will not be able to login to GitLab.
.clearfix
= link_to 'Block User', block_admin_user_path(@admin_user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small right danger"
.row
.span6
.span6
.actions .actions
= f.submit 'Save', class: "btn primary" = f.submit 'Save', class: "btn save-btn"
- if @admin_user.new_record? - if @admin_user.new_record?
= link_to 'Cancel', admin_users_path, class: "btn" = link_to 'Cancel', admin_users_path, class: "btn cancel-btn"
- else - else
= link_to 'Cancel', admin_user_path(@admin_user), class: "btn" = link_to 'Cancel', admin_user_path(@admin_user), class: "btn cancel-btn"

View file

@ -1,3 +1,3 @@
%h3= @admin_user.name %h3.page_title #{@admin_user.name} &rarr; Edit user
%hr %hr
= render 'form' = render 'form'

View file

@ -1,9 +1,9 @@
%h3 %h3.page_title
Users Users
= link_to 'New User', new_admin_user_path, class: "btn small right" = link_to 'New User', new_admin_user_path, class: "btn small right"
%br %br
= form_tag admin_users_path, method: :get do = form_tag admin_users_path, method: :get, class: 'form-inline' do
= text_field_tag :name, params[:name], class: "xlarge" = text_field_tag :name, params[:name], class: "xlarge"
= submit_tag "Search", class: "btn submit primary" = submit_tag "Search", class: "btn submit primary"
%ul.nav.nav-pills %ul.nav.nav-pills

View file

@ -1,3 +1,3 @@
%h2 New user %h3.page_title New user
%hr %br
= render 'form' = render 'form'

View file

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

View file

@ -20,7 +20,7 @@
= "..." = "..."
= text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge" = text_field_tag :to, params[:to], placeholder: "aa8b4ef", class: "xlarge"
.actions .actions
= submit_tag "Compare", class: "btn btn-primary" = submit_tag "Compare", class: "btn primary"
- unless @commits.empty? - unless @commits.empty?

View file

@ -5,12 +5,6 @@
:javascript :javascript
$(document).ready(function(){ $(function(){
$(".line_note_link, .line_note_reply_link").live("click", function(e) { PerLineNotes.init();
var form = $(".per_line_form");
$(this).parent().parent().after(form);
form.find("#note_line_code").val($(this).attr("line_code"));
form.show();
return false;
});
}); });

View file

@ -1,14 +1,7 @@
- if @projects.any? - if @projects.any?
.projects .projects
.activities.span8 .activities.span8
- if current_user.require_ssh_key? = render 'shared/no_ssh'
.alert.alert-error.padded
%span
You wont be able to pull/push project code unless you
%strong
= link_to new_key_path, class: "vlink" do
add new key
to your profile
- if @events.any? - if @events.any?
.content_list= render @events .content_list= render @events
- else - else
@ -26,13 +19,16 @@
= link_to new_project_path, class: "btn very_small info" do = link_to new_project_path, class: "btn very_small info" do
%i.icon-plus %i.icon-plus
New Project New Project
%ul.unstyled
- @projects.each do |project| - @projects.each do |project|
%li.wll
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
%h4 %strong.project_name= truncate(project.name, length: 25)
%span.ico.project %span.arrow
= truncate(project.name, length: 25)
%span.right
&rarr; &rarr;
%span.last_activity
%strong Last activity:
%span= project_last_activity(project)
.bottom= paginate @projects, theme: "gitlab" .bottom= paginate @projects, theme: "gitlab"
%hr %hr

View file

@ -21,7 +21,5 @@
Permissions: Permissions:
%pre %pre
= preserve do = preserve do
sudo chmod -R 770 /home/git/repositories/ sudo chmod -R 770 #{Gitlab.config.git_base_path}
sudo chown -R git:git /home/git/repositories/ sudo chown -R git:git #{Gitlab.config.git_base_path}
sudo chown gitlab:gitlab /home/git/repositories/**/hooks/post-receive

View file

@ -0,0 +1,3 @@
%h1 Git Error
%hr
%p Seems like SSH Key you provided is not a valid SSH key.

View file

@ -9,5 +9,5 @@
at at
%strong= link_to event.project.name, event.project %strong= link_to event.project.name, event.project
= link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn very_small primary" do = link_to new_mr_path_from_push_event(event), title: "New Merge Request", class: "btn very_small" do
Create Merge Request Create Merge Request

View file

@ -9,6 +9,8 @@
%a{href: "#README"} README %a{href: "#README"} README
%li %li
%a{href: "#projects"} Projects %a{href: "#projects"} Projects
%li
%a{href: "#snippets"} Snippets
%li %li
%a{href: "#users"} Users %a{href: "#users"} Users
%li %li
@ -34,6 +36,16 @@
%br %br
.file_holder#snippets
.file_title
%i.icon-file
Projects Snippets
.file_content.wiki
= preserve do
= markdown File.read(Rails.root.join("doc", "api", "snippets.md"))
%br
.file_holder#users .file_holder#users
.file_title .file_title
%i.icon-file %i.icon-file
@ -51,3 +63,13 @@
.file_content.wiki .file_content.wiki
= preserve do = preserve do
= markdown File.read(Rails.root.join("doc", "api", "issues.md")) = markdown File.read(Rails.root.join("doc", "api", "issues.md"))
%br
.file_holder#milestones
.file_title
%i.icon-file
Milestones
.file_content.wiki
= preserve do
= markdown File.read(Rails.root.join("doc", "api", "milestones.md"))

View file

@ -31,3 +31,6 @@
%li %li
%h5= link_to "Gitlab Markdown", help_markdown_path %h5= link_to "Gitlab Markdown", help_markdown_path
%li
%h5= link_to "SSH keys", help_ssh_path

View file

@ -1,25 +1,105 @@
- bash_lexer = Pygments::Lexer[:bash] %h3.page_title Gitlab Flavored Markdown
%h3.page_title Gitlab Markdown
.back_link .back_link
= link_to help_path do = link_to help_path do
&larr; to index &larr; to index
%hr %hr
%p.slead We extend Markdown with some GITLAB specific syntax. It allows you to link to: .row
.span8
%p
For Gitlab we developed something we call "Gitlab Flavored Markdown" (GFM).
It extends the standard Markdown in a few significant ways adds some useful functionality.
%ul %p You can use GFM in:
%li issues (#123) %ul
%li merge request (!123)
%li commits (1234567)
%li team members (@foo)
%li snippets ($123)
%p.slead in
%ul
%li commit messages %li commit messages
%li notes/comments/wall posts %li comments
%li wall posts
%li issues %li issues
%li merge requests %li merge requests
%li milestones %li milestones
%li wiki pages %li wiki pages
%h3 Differences from traditional Markdown
%h4 Newlines
%p
The biggest difference that GFM introduces is in the handling of linebreaks.
With traditional Markdown you can hard wrap paragraphs of text and they will be combined into a single paragraph. We find this to be the cause of a huge number of unintentional formatting errors.
GFM treats newlines in paragraph-like content as real line breaks, which is probably what you intended.
%p The next paragraph contains two phrases separated by a single newline character:
%pre= "Roses are red\nViolets are blue"
%p becomes
= markdown "Roses are red\nViolets are blue"
%h4 Multiple underscores in words
%p
It is not reasonable to italicize just <em>part</em> of a word, especially when you're dealing with code and names often appear with multiple underscores.
Therefore, GFM ignores multiple underscores in words.
%pre= "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
%p becomes
= markdown "perform_complicated_task\ndo_this_and_do_that_and_another_thing"
%h4 URL autolinking
%p
GFM will autolink standard URLs you copy and paste into your text.
So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL.
%h4 Fenced code blocks
%p
Markdown converts text with four spaces at the front of each line to code blocks.
GFM supports that, but we also support fenced blocks.
Just wrap your code blocks in <code>```</code> and you won't need to indent manually to trigger a code block.
%pre= %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
%p becomes
= markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
%h4 Special Gitlab references
%p
GFM recognizes special references.
You can easily reference e.g. a team member, an issue or a commit within a project.
GFM will turn that reference into a link so you can navigate between them easily.
%p GFM will recognize the following references:
%ul
%li
%code @foo
for team members
%li
%code #123
for issues
%li
%code !123
for merge request
%li
%code $123
for snippets
%li
%code 1234567
for commits
-# this example will only be shown if the user has a project with at least one issue
- if @project = current_user.projects.first
- if issue = @project.issues.first
%p For example in your #{link_to @project.name, project_path(@project)} project something like
%pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
%p becomes
= markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
.span4.right
.alert.alert-info
%p
If you're not already familiar with Markdown, you should spend 15 minutes and go over the excellent
%strong= link_to "Markdown Syntax Guide", "http://daringfireball.net/projects/markdown/syntax"
at Daring Fireball.

View file

@ -1,4 +1,4 @@
%h3 Permissions %h3.page_title Permissions
.back_link .back_link
= link_to help_path do = link_to help_path do
&larr; to index &larr; to index

View file

@ -0,0 +1,25 @@
%h3.page_title SSH Keys
.back_link
= link_to help_path do
&larr; to index
%hr
%p.slead
SSH key allows you to establish a secure connection between your computer and Gitlab
%p.slead
To generate a new SSH key just open your terminal and use code below.
%pre.dark
ssh-keygen -t rsa -C "#{current_user.email}"
\# Creates a new ssh key using the provided email
\# Generating public/private rsa key pair...
%p.slead
Next just use code below to dump your public key and add to GITLAB SSH Keys
%pre.dark
cat ~/.ssh/id_rsa.pub
\# ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6eNtGpNGwstc....

View file

@ -1,4 +1,4 @@
%h3 Web hooks %h3.page_title Web hooks
.back_link .back_link
= link_to help_path do = link_to help_path do
&larr; to index &larr; to index

View file

@ -1,5 +1,4 @@
- bash_lexer = Pygments::Lexer[:bash] %h3.page_title Workflow
%h3 Workflow
.back_link .back_link
= link_to help_path do = link_to help_path do
&larr; to index &larr; to index
@ -9,25 +8,25 @@
%li %li
%p Clone project %p Clone project
.bash .bash
%pre %pre.dark
git clone git@example.com:project-name.git git clone git@example.com:project-name.git
%li %li
%p Create branch with your feature %p Create branch with your feature
.bash .bash
%pre %pre.dark
git checkout -b $feature_name git checkout -b $feature_name
%li %li
%p Write code. Commit changes %p Write code. Commit changes
.bash .bash
%pre %pre.dark
git commit -am "My feature is ready" git commit -am "My feature is ready"
%li %li
%p Push your branch to gitlabhq %p Push your branch to gitlabhq
.bash .bash
%pre %pre.dark
git push origin $feature_name git push origin $feature_name
%li %li

View file

@ -37,7 +37,7 @@
} }
} }
], ],
total_commits_count => 3 total_commits_count => 4
} }
eos eos
%> %>

View file

@ -8,7 +8,7 @@
Read more about web hooks Read more about web hooks
%strong #{link_to "here", help_web_hooks_path, class: "vlink"} %strong #{link_to "here", help_web_hooks_path, class: "vlink"}
= form_for [@project, @hook], as: :hook, url: project_hooks_path(@project) do |f| = form_for [@project, @hook], as: :hook, url: project_hooks_path(@project), html: { class: 'form-inline' } do |f|
-if @hook.errors.any? -if @hook.errors.any?
.alert-message.block-message.error .alert-message.block-message.error
- @hook.errors.full_messages.each do |msg| - @hook.errors.full_messages.each do |msg|

View file

@ -38,19 +38,20 @@
= f.label :description, "Details" = f.label :description, "Details"
.input .input
= f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14 = f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14
%p.hint Markdown is enabled. %p.hint Issues are parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
.actions .actions
- if @issue.new_record? - if @issue.new_record?
= f.submit 'Submit new issue', class: "primary btn" = f.submit 'Submit new issue', class: "btn save-btn"
-else -else
= f.submit 'Save changes', class: "primary btn" = f.submit 'Save changes', class: "save-btn btn"
- cancel_class = 'btn cancel-btn'
- if request.xhr? - if request.xhr?
= link_to "Cancel", "#back", onclick: "backToIssues();", class: "btn" = link_to "Cancel", "#back", onclick: "backToIssues();", class: cancel_class
- else - else
- if @issue.new_record? - if @issue.new_record?
= link_to "Cancel", project_issues_path(@project), class: "btn" = link_to "Cancel", project_issues_path(@project), class: cancel_class
- else - else
= link_to "Cancel", project_issue_path(@project, @issue), class: "btn" = link_to "Cancel", project_issue_path(@project, @issue), class: cancel_class

View file

@ -5,6 +5,9 @@
%li{class: "#{'active' if current_page?(project_milestones_path(@project))}"} %li{class: "#{'active' if current_page?(project_milestones_path(@project))}"}
= link_to project_milestones_path(@project), class: "tab" do = link_to project_milestones_path(@project), class: "tab" do
Milestones Milestones
%li{class: "#{'active' if current_page?(project_labels_path(@project))}"}
= link_to project_labels_path(@project), class: "tab" do
Labels
%li.right %li.right
%span.rss-icon %span.rss-icon
= link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do = link_to project_issues_path(@project, :atom, { private_token: current_user.private_token }) do

View file

@ -6,7 +6,7 @@
.right .right
.span5 .span5
- if can? current_user, :write_issue, @project - if can? current_user, :write_issue, @project
= link_to new_project_issue_path(@project), class: "right btn small", title: "New Issue", remote: true do = link_to new_project_issue_path(@project), class: "right btn", title: "New Issue", remote: true do
%i.icon-plus %i.icon-plus
New Issue New Issue
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do = form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do

View file

@ -11,8 +11,14 @@
.input= f.text_field :title .input= f.text_field :title
.clearfix .clearfix
= f.label :key = f.label :key
.input= f.text_area :key, class: [:xxlarge, :thin_area] .input
.actions = f.text_area :key, class: [:xxlarge, :thin_area]
= f.submit 'Save', class: "primary btn" %p.hint
= link_to "Cancel", keys_path, class: "btn" Paste your public key here. Read more about how generate it
= link_to "here", help_ssh_path
.actions
= f.submit 'Save', class: "btn save-btn"
= link_to "Cancel", keys_path, class: "btn cancel-btn"

View file

@ -1,6 +1,6 @@
%h3.page_title %h3.page_title
SSH Keys SSH Keys
= link_to "Add new", new_key_path, class: "btn small right" = link_to "Add new", new_key_path, class: "btn right"
%hr %hr
%p.slead %p.slead

View file

@ -1,4 +1,4 @@
%h3.page_title New key %h3.page_title Add an SSH Key
%hr %hr
= render 'form' = render 'form'

View file

@ -0,0 +1,4 @@
%li.wll
%strong= label.name
.right
%span= pluralize label.count, 'issue'

View file

@ -0,0 +1,14 @@
= render "issues/head"
%h3.page_title
Labels
%br
%div.ui-box
%ul.unstyled.labels-table
- @labels.each do |label|
= render 'label', label: label
- unless @labels.present?
%li
%h3.nothing_here_message Nothing to show here

View file

@ -9,7 +9,7 @@
%br %br
.row .row
.span6 .span5
.mr_branch_box .mr_branch_box
%h5 From (Head Branch) %h5 From (Head Branch)
.body .body
@ -17,10 +17,11 @@
= f.label :source_branch, "From", class: "control-label" = f.label :source_branch, "From", class: "control-label"
.controls .controls
= f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px") = f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
.bottom_commit
.mr_source_commit .mr_source_commit
.span6 .span2
%center= image_tag "merge.png", class: 'mr_direction_tip'
.span5
.mr_branch_box .mr_branch_box
%h5 To (Base Branch) %h5 To (Base Branch)
.body .body
@ -28,7 +29,6 @@
= f.label :target_branch, "To", class: "control-label" = f.label :target_branch, "To", class: "control-label"
.controls .controls
= f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px") = f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
.bottom_commit
.mr_target_commit .mr_target_commit
%h4.cdark 2. Fill info %h4.cdark 2. Fill info
@ -48,18 +48,19 @@
.control-group .control-group
.form-actions .form-actions
= f.submit 'Save', class: "btn-primary btn" = f.submit 'Save', class: "btn save-btn"
- if @merge_request.new_record? - if @merge_request.new_record?
= link_to project_merge_requests_path(@project), class: "btn" do = link_to project_merge_requests_path(@project), class: "btn cancel-btn" do
Cancel Cancel
- else - else
= link_to project_merge_request_path(@project, @merge_request), class: "btn" do = link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
Cancel Cancel
:javascript :javascript
$(function(){ $(function(){
disableButtonIfEmtpyField("#merge_request_title", ".save-btn");
$('select#merge_request_assignee_id').chosen(); $('select#merge_request_assignee_id').chosen();
$('select#merge_request_source_branch').chosen(); $('select#merge_request_source_branch').chosen();
$('select#merge_request_target_branch').chosen(); $('select#merge_request_target_branch').chosen();

View file

@ -1,7 +1,7 @@
%h3.page_title %h3.page_title
Merge Requests Merge Requests
- if can? current_user, :write_issue, @project - if can? current_user, :write_issue, @project
= link_to new_project_merge_request_path(@project), class: "right btn small", title: "New Merge Request" do = link_to new_project_merge_request_path(@project), class: "right btn", title: "New Merge Request" do
New Merge Request New Merge Request
%br %br
@ -10,17 +10,17 @@
.ui-box .ui-box
.title .title
%ul.nav.nav-pills %ul.nav.nav-pills
%li{class: ("active" if (params[:f] == "0" || !params[:f]))} %li{class: ("active" if (params[:f] == 'open' || !params[:f]))}
= link_to project_merge_requests_path(@project, f: 0) do = link_to project_merge_requests_path(@project, f: 'open') do
Open Open
%li{class: ("active" if params[:f] == "2")} %li{class: ("active" if params[:f] == "closed")}
= link_to project_merge_requests_path(@project, f: 2) do = link_to project_merge_requests_path(@project, f: "closed") do
Closed Closed
%li{class: ("active" if params[:f] == "3")} %li{class: ("active" if params[:f] == 'assigned-to-me')}
= link_to project_merge_requests_path(@project, f: 3) do = link_to project_merge_requests_path(@project, f: 'assigned-to-me') do
To Me To Me
%li{class: ("active" if params[:f] == "1")} %li{class: ("active" if params[:f] == 'all')}
= link_to project_merge_requests_path(@project, f: 1) do = link_to project_merge_requests_path(@project, f: 'all') do
All All
%ul.unstyled %ul.unstyled

View file

@ -3,13 +3,12 @@
%a.close{href: "#"} × %a.close{href: "#"} ×
%h3 How To Merge %h3 How To Merge
.modal-body .modal-body
%pre %pre.dark
= preserve do = preserve do
:erb git checkout #{@merge_request.target_branch}
git checkout <%= @merge_request.target_branch %>
git fetch origin git fetch origin
git merge origin/<%= @merge_request.source_branch %> git merge origin/#{@merge_request.source_branch}
git push origin <%= @merge_request.target_branch %> git push origin #{@merge_request.target_branch}
:javascript :javascript

View file

@ -1,9 +1,9 @@
%h3.page_title %h3.page_title
= "Merge Request ##{@merge_request.id}:" = "Merge Request ##{@merge_request.id}:"
&nbsp; &nbsp;
%span.pretty_label.branch= @merge_request.source_branch %span.label_branch= @merge_request.source_branch
&rarr; &rarr;
%span.pretty_label.branch= @merge_request.target_branch %span.label_branch= @merge_request.target_branch
%span.right %span.right
- if @merge_request.merged? - if @merge_request.merged?

View file

@ -22,7 +22,7 @@
= f.label :description, "Description", class: "control-label" = f.label :description, "Description", class: "control-label"
.controls .controls
= f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10 = f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10
%p.hint Markdown is enabled. %p.hint Milestones are parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
.span6 .span6
.control-group .control-group
= f.label :due_date, "Due Date", class: "control-label" = f.label :due_date, "Due Date", class: "control-label"
@ -32,20 +32,16 @@
.form-actions .form-actions
- if @milestone.new_record? - if @milestone.new_record?
= f.submit 'Create milestone', class: "primary btn" = f.submit 'Create milestone', class: "save-btn btn"
= link_to "Cancel", project_milestones_path(@project), class: "btn cancel-btn"
-else -else
= f.submit 'Save changes', class: "primary btn" = f.submit 'Save changes', class: "save-btn btn"
= link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn cancel-btn"
- if request.xhr?
= link_to "Cancel", "#back", onclick: "backToIssues();", class: "btn"
- else
- if @milestone.new_record?
= link_to "Cancel", project_milestones_path(@project), class: "btn"
- else
= link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn"
:javascript :javascript
$(function() { $(function() {
disableButtonIfEmtpyField("#milestone_title", ".save-btn");
$( ".datepicker" ).datepicker({ $( ".datepicker" ).datepicker({
dateFormat: "yy-mm-dd", dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) } onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }

View file

@ -8,11 +8,11 @@
%div.ui-box %div.ui-box
.title .title
%ul.nav.nav-pills %ul.nav.nav-pills
%li{class: ("active" if (params[:f] == "0" || !params[:f]))} %li{class: ("active" if (params[:f] == "active" || !params[:f]))}
= link_to project_milestones_path(@project, f: 0) do = link_to project_milestones_path(@project, f: "active") do
Active Active
%li{class: ("active" if params[:f] == "1")} %li{class: ("active" if params[:f] == "all")}
= link_to project_milestones_path(@project, f: 1) do = link_to project_milestones_path(@project, f: "all") do
All All
%ul.unstyled %ul.unstyled

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