Commit bdac5ddd authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ee-from-ce' into 'master'

CE changes from master

Sidebar navigation, OAuth and other changes from CE

See merge request !275
parents 4f0d2d33 01f7734f
v 7.7.0
-
-
-
-
-
-
-
-
- OAuth applications feature
-
-
- Set project path instead of project name in create form
-
-
- New side navigation
v 7.6.0 v 7.6.0
- Fork repository to groups - Fork repository to groups
- New rugged version - New rugged version
......
...@@ -101,6 +101,16 @@ Please ensure you support the feature you contribute through all of these steps. ...@@ -101,6 +101,16 @@ Please ensure you support the feature you contribute through all of these steps.
1. Community questions answered 1. Community questions answered
1. Answers to questions radiated (in docs/wiki/etc.) 1. Answers to questions radiated (in docs/wiki/etc.)
If you add a dependency in GitLab (such as an operating system package) please consider updating the following and note the applicability of each in your merge request:
1. Note the addition in the release blog post (create one if it doesn't exist yet) https://gitlab.com/gitlab-com/www-gitlab-com/merge_requests/
1. Upgrade guide, for example https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/7.5-to-7.6.md
1. Upgrader https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md#2-run-gitlab-upgrade-tool
1. Installation guide https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies
1. GitLab Development Kit https://gitlab.com/gitlab-org/gitlab-development-kit
1. Test suite https://gitlab.com/gitlab-org/gitlab-ci/blob/master/doc/examples/configure_a_runner_to_run_the_gitlab_ce_test_suite.md
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
## Merge request description format ## Merge request description format
1. What does this MR do? 1. What does this MR do?
...@@ -118,6 +128,7 @@ Please ensure you support the feature you contribute through all of these steps. ...@@ -118,6 +128,7 @@ Please ensure you support the feature you contribute through all of these steps.
1. Can merge without problems (if not please merge `master`, never rebase commits pushed to the remote server) 1. Can merge without problems (if not please merge `master`, never rebase commits pushed to the remote server)
1. Does not break any existing functionality 1. Does not break any existing functionality
1. Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed) 1. Fixes one specific issue or implements one specific feature (do not combine things, send separate merge requests if needed)
1. Migrations should do only one thing (eg: either create a table, move data to a new table or remove an old table) to aid retrying on failure
1. Keeps the GitLab code base clean and well structured 1. Keeps the GitLab code base clean and well structured
1. Contains functionality we think other users will benefit from too 1. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options since they complicate future changes 1. Doesn't add configuration options since they complicate future changes
......
...@@ -29,6 +29,8 @@ gem 'omniauth-twitter' ...@@ -29,6 +29,8 @@ gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
gem 'omniauth-shibboleth' gem 'omniauth-shibboleth'
gem 'omniauth-kerberos' gem 'omniauth-kerberos'
gem 'doorkeeper', '2.0.1'
gem "rack-oauth2", "~> 1.0.5"
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
......
...@@ -37,6 +37,7 @@ GEM ...@@ -37,6 +37,7 @@ GEM
rake (>= 0.8.7) rake (>= 0.8.7)
arel (5.0.1.20140414130214) arel (5.0.1.20140414130214)
asciidoctor (0.1.4) asciidoctor (0.1.4)
attr_required (1.0.0)
awesome_print (1.2.0) awesome_print (1.2.0)
axiom-types (0.0.5) axiom-types (0.0.5)
descendants_tracker (~> 0.0.1) descendants_tracker (~> 0.0.1)
...@@ -107,6 +108,8 @@ GEM ...@@ -107,6 +108,8 @@ GEM
diff-lcs (1.2.5) diff-lcs (1.2.5)
diffy (3.0.3) diffy (3.0.3)
docile (1.1.5) docile (1.1.5)
doorkeeper (2.0.1)
railties (>= 3.1)
dotenv (0.9.0) dotenv (0.9.0)
dropzonejs-rails (0.4.14) dropzonejs-rails (0.4.14)
rails (> 3.1) rails (> 3.1)
...@@ -158,7 +161,7 @@ GEM ...@@ -158,7 +161,7 @@ GEM
dotenv (>= 0.7) dotenv (>= 0.7)
thor (>= 0.13.6) thor (>= 0.13.6)
formatador (0.2.4) formatador (0.2.4)
gemnasium-gitlab-service (0.2.2) gemnasium-gitlab-service (0.2.3)
rugged (~> 0.19) rugged (~> 0.19)
gherkin-ruby (0.3.1) gherkin-ruby (0.3.1)
racc racc
...@@ -250,6 +253,7 @@ GEM ...@@ -250,6 +253,7 @@ GEM
json (~> 1.8) json (~> 1.8)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
httpauth (0.2.1) httpauth (0.2.1)
httpclient (2.5.3.3)
i18n (0.6.11) i18n (0.6.11)
ice_cube (0.12.1) ice_cube (0.12.1)
ice_nine (0.10.0) ice_nine (0.10.0)
...@@ -369,6 +373,12 @@ GEM ...@@ -369,6 +373,12 @@ GEM
rack (>= 1.1.3) rack (>= 1.1.3)
rack-mount (0.8.3) rack-mount (0.8.3)
rack (>= 1.0.0) rack (>= 1.0.0)
rack-oauth2 (1.0.8)
activesupport (>= 2.3)
attr_required (>= 0.0.5)
httpclient (>= 2.2.0.2)
multi_json (>= 1.3.6)
rack (>= 1.1)
rack-protection (1.5.1) rack-protection (1.5.1)
rack rack
rack-test (0.6.2) rack-test (0.6.2)
...@@ -621,6 +631,7 @@ DEPENDENCIES ...@@ -621,6 +631,7 @@ DEPENDENCIES
devise (= 3.2.4) devise (= 3.2.4)
devise-async (= 0.9.0) devise-async (= 0.9.0)
diffy (~> 3.0.3) diffy (~> 3.0.3)
doorkeeper (= 2.0.1)
dropzonejs-rails dropzonejs-rails
email_spec email_spec
enumerize enumerize
...@@ -678,6 +689,7 @@ DEPENDENCIES ...@@ -678,6 +689,7 @@ DEPENDENCIES
rack-attack rack-attack
rack-cors rack-cors
rack-mini-profiler rack-mini-profiler
rack-oauth2 (~> 1.0.5)
rails (~> 4.1.0) rails (~> 4.1.0)
rails_autolink (~> 1.1) rails_autolink (~> 1.1)
rails_best_practices rails_best_practices
......
...@@ -76,69 +76,30 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a ...@@ -76,69 +76,30 @@ On [about.gitlab.com](https://about.gitlab.com/) you can find more information a
Please see [the installation page on the GitLab website](https://about.gitlab.com/installation/) for the various options. Please see [the installation page on the GitLab website](https://about.gitlab.com/installation/) for the various options.
Since a manual installation is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm). Since a manual installation is a lot of work and error prone we strongly recommend the fast and reliable [Omnibus package installation](https://about.gitlab.com/downloads/) (deb/rpm).
You can access new installation with the login `root` and password `5iveL!fe`, after login you are required to set a unique password.
## Third-party applications ## Third-party applications
There are a lot of applications and API wrappers for GitLab. There are a lot of applications and API wrappers for GitLab.
Find them [on our website](https://about.gitlab.com/applications/). Find them [on our website](https://about.gitlab.com/applications/).
### New versions ## New versions
Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases come out when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the release [documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457). Since 2011 a minor or major version of GitLab is released on the 22nd of every month. Patch and security releases come out when needed. New features are detailed on the [blog](https://about.gitlab.com/blog/) and in the [changelog](CHANGELOG). For more information about the release process see the release [documentation](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/release). Features that will likely be in the next releases can be found on the [feature request forum](http://feedback.gitlab.com/forums/176466-general) with the status [started](http://feedback.gitlab.com/forums/176466-general/status/796456) and [completed](http://feedback.gitlab.com/forums/176466-general/status/796457).
### Upgrading ## Upgrading
For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update). For updating the the Omnibus installation please see the [update documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/update.md). For manual installations there is an [upgrader script](doc/update/upgrader.md) and there are [upgrade guides](doc/update).
## Run in production mode
The Installation guide contains instructions on how to download an init script and run it automatically on boot. You can also start the init script manually:
sudo service gitlab start
or by directly calling the script:
sudo /etc/init.d/gitlab start
Please login with `root` / `5iveL!fe`
## Install a development environment ## Install a development environment
We recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit). We recommend setting up your development environment with [the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit).
If you do not use the development kit you might need to copy the example development unicorn configuration file If you do not use the GitLab Development Development kit you need to install and setup all the dependencies yourself, this is a lot of work and error prone.
One small thing you also have to do when installing it yourself is to copy the example development unicorn configuration file:
cp config/unicorn.rb.example.development config/unicorn.rb cp config/unicorn.rb.example.development config/unicorn.rb
## Run in development mode Instructions on how to start Gitlab and how to run the tests can be found in the [development section of the GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit#development).
Start it with [Foreman](https://github.com/ddollar/foreman)
bundle exec foreman start -p 3000
or start each component separately:
bundle exec rails s
bin/background_jobs start
And surf to [localhost:3000](http://localhost:3000/) and login with `root` / `5iveL!fe`.
## Run the tests
- Run all tests:
bundle exec rake test
- [RSpec](http://rspec.info/) unit and functional tests.
All RSpec tests: `bundle exec rake spec`
Single RSpec file: `bundle exec rspec spec/controllers/commit_controller_spec.rb`
- [Spinach](https://github.com/codegram/spinach) integration tests.
All Spinach tests: `bundle exec rake spinach`
Single Spinach test: `bundle exec spinach features/project/issues/milestones.feature`
## Documentation ## Documentation
......
...@@ -12,7 +12,7 @@ class @Activities ...@@ -12,7 +12,7 @@ class @Activities
toggleFilter: (sender) -> toggleFilter: (sender) ->
sender.parent().toggleClass "inactive" sender.parent().toggleClass "active"
event_filters = $.cookie("event_filter") event_filters = $.cookie("event_filter")
filter = sender.attr("id").split("_")[0] filter = sender.attr("id").split("_")[0]
if event_filters if event_filters
......
...@@ -51,12 +51,6 @@ window.ajaxGet = (url) -> ...@@ -51,12 +51,6 @@ window.ajaxGet = (url) ->
window.showAndHide = (selector) -> window.showAndHide = (selector) ->
window.errorMessage = (message) ->
ehtml = $("<p>")
ehtml.addClass("error_message")
ehtml.html(message)
ehtml
window.split = (val) -> window.split = (val) ->
return val.split( /,\s*/ ) return val.split( /,\s*/ )
......
class @Issue class @Issue
constructor: -> constructor: ->
$('.edit-issue.inline-update input[type="submit"]').hide() $('.edit-issue.inline-update input[type="submit"]').hide()
$(".issue-box .inline-update").on "change", "select", -> $(".context .inline-update").on "change", "select", ->
$(this).submit() $(this).submit()
$(".issue-box .inline-update").on "change", "#issue_assignee_id", -> $(".context .inline-update").on "change", "#issue_assignee_id", ->
$(this).submit() $(this).submit()
if $("a.btn-close").length if $("a.btn-close").length
......
...@@ -26,9 +26,9 @@ class @MergeRequest ...@@ -26,9 +26,9 @@ class @MergeRequest
initContextWidget: -> initContextWidget: ->
$('.edit-merge_request.inline-update input[type="submit"]').hide() $('.edit-merge_request.inline-update input[type="submit"]').hide()
$(".issue-box .inline-update").on "change", "select", -> $(".context .inline-update").on "change", "select", ->
$(this).submit() $(this).submit()
$(".issue-box .inline-update").on "change", "#merge_request_assignee_id", -> $(".context .inline-update").on "change", "#merge_request_assignee_id", ->
$(this).submit() $(this).submit()
initMergeWidget: -> initMergeWidget: ->
...@@ -89,6 +89,9 @@ class @MergeRequest ...@@ -89,6 +89,9 @@ class @MergeRequest
this.$('.merge-request-tabs .diffs-tab').addClass 'active' this.$('.merge-request-tabs .diffs-tab').addClass 'active'
this.loadDiff() unless @diffs_loaded this.loadDiff() unless @diffs_loaded
this.$('.diffs').show() this.$('.diffs').show()
when 'commits'
this.$('.merge-request-tabs .commits-tab').addClass 'active'
this.$('.commits').show()
else else
this.$('.merge-request-tabs .notes-tab').addClass 'active' this.$('.merge-request-tabs .notes-tab').addClass 'active'
this.$('.notes').show() this.$('.notes').show()
......
...@@ -375,7 +375,7 @@ class @Notes ...@@ -375,7 +375,7 @@ class @Notes
### ###
addDiffNote: (e) => addDiffNote: (e) =>
e.preventDefault() e.preventDefault()
link = e.target link = e.currentTarget
form = $(".js-new-note-form") form = $(".js-new-note-form")
row = $(link).closest("tr") row = $(link).closest("tr")
nextRow = row.next() nextRow = row.next()
......
...@@ -46,7 +46,7 @@ class @ContributorsGraph ...@@ -46,7 +46,7 @@ class @ContributorsGraph
class @ContributorsMasterGraph extends ContributorsGraph class @ContributorsMasterGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
@width = $('.container').width() - 70 @width = $('.container').width() - 345
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
...@@ -119,7 +119,7 @@ class @ContributorsMasterGraph extends ContributorsGraph ...@@ -119,7 +119,7 @@ class @ContributorsMasterGraph extends ContributorsGraph
class @ContributorsAuthorGraph extends ContributorsGraph class @ContributorsAuthorGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
@width = $('.container').width()/2 - 100 @width = $('.container').width()/2 - 225
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
......
/** /**
* Issue box: * Issue box for showing Open/Closed state:
* Huge block (one per page) for storing title, descripion and other information.
* Used for Issue#show page, MergeRequest#show page etc * Used for Issue#show page, MergeRequest#show page etc
* *
* CLasses:
* .issue-box - Regular box
*/ */
.issue-box { .issue-box {
color: #555; display: inline-block;
margin:20px 0; padding: 7px 13px;
background: $box_bg; font-weight: normal;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); margin-right: 5px;
&.issue-box-closed { &.issue-box-closed {
.state { background-color: $bg_danger;
background-color: #F3CECE; color: #FFF;
border-color: $border_danger;
}
.state-label {
background-color: $bg_danger;
color: #FFF;
}
} }
&.issue-box-merged { &.issue-box-merged {
.state { background-color: $bg_primary;
background-color: #B7CEE7; color: #FFF;
border-color: $border_primary;
}
.state-label {
background-color: $bg_primary;
color: #FFF;
}
} }
&.issue-box-open { &.issue-box-open {
.state { background-color: $bg_success;
background-color: #D6F1D7; color: #FFF;
border-color: $bg_success;
}
.state-label {
background-color: $bg_success;
color: #FFF;
}
} }
&.issue-box-expired { &.issue-box-expired {
.state { background: #cea61b;
background-color: #EEE9B3; color: #FFF;
border-color: #faebcc;
}
.state-label {
background: #cea61b;
color: #FFF;
}
}
.control-group {
margin-bottom: 0;
}
.state {
background-color: #f9f9f9;
}
.title {
font-size: 28px;
font-weight: normal;
line-height: 1.5;
margin: 0;
color: #333;
padding: 10px 15px;
}
.context {
border: none;
border-top: 1px solid #eee;
padding: 10px 15px;
// Reset text align for children
.text-right > * { text-align: left; }
@media (max-width: $screen-xs-max) {
// Don't right align on mobile
.text-right { text-align: left; }
.row .col-md-6 {
padding-top: 5px;
}
}
}
.description {
padding: 0 15px 10px 15px;
code {
white-space: pre-wrap;
}
}
.title, .context, .description {
.clearfix {
margin: 0;
}
}
.state-label {
font-size: 14px;
float: left;
font-weight: bold;
padding: 10px 15px;
}
.cross-project-ref {
float: left;
padding: 10px 15px;
}
.creator {
float: right;
padding: 10px 15px;
a {
text-decoration: underline;
}
} }
} }
table {
&.table {
tr {
td, th {
padding: 8px 10px;
line-height: 20px;
vertical-align: middle;
}
th {
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid #CCC !important;
}
td {
border-color: #F1F1F1 !important;
border-bottom: 1px solid;
}
}
}
}
...@@ -74,6 +74,42 @@ ...@@ -74,6 +74,42 @@
} }
} }
} }
.system-note .timeline-entry-inner {
.timeline-icon {
background: none;
margin-left: 12px;
margin-top: 0;
@include box-shadow(none);
span {
margin: 0 2px;
font-size: 16px;
color: #eeeeee;
}
}
.timeline-content {
background: none;
margin-left: 45px;
padding: 0px 15px;
&:after { border: 0; }
.note-header {
span { font-size: 12px; }
.avatar {
margin-right: 5px;
}
}
.note-text {
font-size: 12px;
margin-left: 20px;
}
}
}
} }
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
......
...@@ -148,6 +148,10 @@ $list-group-active-bg: $bg_primary; ...@@ -148,6 +148,10 @@ $list-group-active-bg: $bg_primary;
color: #666; color: #666;
} }
.nav-compact > li > a {
padding: 6px 12px;
}
.nav-small > li > a { .nav-small > li > a {
padding: 3px 5px; padding: 3px 5px;
font-size: 12px; font-size: 12px;
......
...@@ -4,10 +4,6 @@ html { ...@@ -4,10 +4,6 @@ html {
&.touch .tooltip { display: none !important; } &.touch .tooltip { display: none !important; }
} }
body {
padding-bottom: 20px;
}
.container { .container {
padding-top: 0; padding-top: 0;
z-index: 5; z-index: 5;
......
...@@ -44,6 +44,6 @@ $added: #63c363; ...@@ -44,6 +44,6 @@ $added: #63c363;
$deleted: #f77; $deleted: #f77;
/** /**
* * NProgress customize
*/ */
$nprogress-color: #3498db; $nprogress-color: #3498db;
...@@ -23,20 +23,6 @@ ...@@ -23,20 +23,6 @@
} }
} }
.dashboard {
.dash-filter {
width: 205px;
float: left;
height: inherit;
}
}
@media (max-width: 1200px) {
.dashboard .dash-filter {
width: 140px;
}
}
.dash-sidebar-tabs { .dash-sidebar-tabs {
margin-bottom: 2px; margin-bottom: 2px;
border: none; border: none;
......
...@@ -140,36 +140,6 @@ ...@@ -140,36 +140,6 @@
} }
} }
/**
* Event filter
*
*/
.event_filter {
position: absolute;
width: 40px;
margin-left: -55px;
.filter_icon {
a {
text-align:center;
background: $bg_primary;
margin-bottom: 10px;
float: left;
padding: 9px 6px;
font-size: 18px;
width: 40px;
color: #FFF;
@include border-radius(3px);
}
&.inactive {
a {
color: #DDD;
background: #f9f9f9;
}
}
}
}
/* /*
* Last push widget * Last push widget
...@@ -203,3 +173,7 @@ ...@@ -203,3 +173,7 @@
} }
} }
} }
.event_filter li a {
padding: 5px 10px;
}
...@@ -52,8 +52,6 @@ header { ...@@ -52,8 +52,6 @@ header {
border-width: 0; border-width: 0;
font-size: 18px; font-size: 18px;
.app_logo { margin-left: -15px; }
.title { .title {
@include str-truncated(70%); @include str-truncated(70%);
} }
...@@ -86,6 +84,11 @@ header { ...@@ -86,6 +84,11 @@ header {
z-index: 10; z-index: 10;
.container {
width: 100% !important;
padding-left: 0px;
}
/** /**
* *
* Logo holder * Logo holder
...@@ -232,21 +235,6 @@ header { ...@@ -232,21 +235,6 @@ header {
color: #fff; color: #fff;
} }
} }
.app_logo {
.separator {
margin-left: 0;
margin-right: 0;
}
}
.separator {
float: left;
height: 46px;
width: 2px;
margin-left: 10px;
margin-right: 10px;
}
} }
.search .search-input { .search .search-input {
......
...@@ -162,3 +162,7 @@ form.edit-issue { ...@@ -162,3 +162,7 @@ form.edit-issue {
} }
} }
} }
.issue-title {
margin-top: 0;
}
...@@ -19,17 +19,15 @@ ...@@ -19,17 +19,15 @@
} }
} }
.merge-request .merge-request-tabs{ @media(min-width: $screen-sm-max) {
border-bottom: 2px solid $border_primary; .merge-request .merge-request-tabs{
margin: 20px 0; margin: 20px 0;
li { li {
a { a {
padding: 15px 40px; padding: 15px 40px;
font-size: 14px; font-size: 14px;
margin-bottom: -2px; }
border-bottom: 2px solid $border_primary;
@include border-radius(0px);
} }
} }
} }
...@@ -106,6 +104,7 @@ ...@@ -106,6 +104,7 @@
.mr-state-widget { .mr-state-widget {
background: $box_bg; background: $box_bg;
margin-bottom: 20px; margin-bottom: 20px;
color: #666;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09)); @include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
.ci_widget { .ci_widget {
...@@ -150,7 +149,6 @@ ...@@ -150,7 +149,6 @@
padding: 10px 15px; padding: 10px 15px;
h4 { h4 {
font-size: 20px;
font-weight: normal; font-weight: normal;
} }
......
.main-nav {
background: #f5f5f5;
margin: 20px 0;
margin-top: 0;
padding-top: 4px;
border-bottom: 1px solid #E9E9E9;
ul {
padding: 0;
margin: auto;
.count {
font-weight: normal;
display: inline-block;
height: 15px;
padding: 1px 6px;
height: auto;
font-size: 0.82em;
line-height: 14px;
text-align: center;
color: #777;
background: #eee;
@include border-radius(8px);
}
.label {
background: $hover;
text-shadow: none;
color: $style_color;
}
li {
list-style-type: none;
margin: 0;
display: table-cell;
width: 1%;
&.active {
a {
color: $link_color;
font-weight: bold;
border-bottom: 3px solid $link_color;
}
}
&:hover {
a {
color: $link_hover_color;
border-bottom: 3px solid $link_hover_color;
}
}
}
a {
display: block;
text-align: center;
font-weight: bold;
height: 42px;
line-height: 39px;
color: #777;
text-shadow: 0 1px 1px white;
text-decoration: none;
overflow: hidden;
margin-bottom: -1px;
}
}
@media (max-width: $screen-xs-max) {
font-size: 18px;
margin: 0;
max-height: none;
&, .container {
padding: 0;
border-top: 0;
}
ul {
height: auto;
li {
display: list-item;
width: auto;
padding: 5px 0;
&.active {
background-color: $link_hover_color;
a {
color: #fff;
font-weight: normal;
text-shadow: none;
border: none;
&:after { display: none; }
}
}
}
}
}
}
...@@ -155,19 +155,26 @@ ul.notes { ...@@ -155,19 +155,26 @@ ul.notes {
} }
.add-diff-note { .add-diff-note {
background: image-url("diff_note_add.png") no-repeat left 0; margin-top: -4px;
border: none; @include border-radius(40px);
height: 22px; background: #FFF;
margin-left: -65px; padding: 4px;
font-size: 16px;
color: $link_color;
margin-left: -60px;
position: absolute; position: absolute;
width: 22px;
z-index: 10; z-index: 10;
transition: all 0.2s ease;
// "hide" it by default // "hide" it by default
opacity: 0.0; opacity: 0.0;
filter: alpha(opacity=0); filter: alpha(opacity=0);
&:hover { &:hover {
font-size: 24px;
background: $bg_primary;
color: #FFF;
@include show-add-diff-note; @include show-add-diff-note;
} }
} }
......
.page-with-sidebar {
background: #F5F5F5;
}
.sidebar-wrapper {
overflow-y: auto;
background: #F5F5F5;
}
.content-wrapper {
width: 100%;
padding: 15px;
background: #FFF;
}
.nav-sidebar {
margin: 0;
list-style: none;
&.navbar-collapse {
padding: 0px !important;
}
}
.nav-sidebar li a .count {
float: right;
background: #eee;
padding: 0px 8px;
@include border-radius(6px);
}
.nav-sidebar li {
&.active a {
color: #111;
background: #EEE;
font-weight: bold;
&.no-highlight {
background: none;
}
i {
color: #444;
}
}
}
.nav-sidebar li {
&.separate-item {
border-top: 1px solid #ddd;
padding-top: 10px;
margin-top: 10px;
}
a {
color: #555;
display: block;
text-decoration: none;
padding: 6px 15px;
font-size: 13px;
line-height: 20px;
text-shadow: 0 1px 2px #FFF;
padding-left: 20px;
&:hover {
text-decoration: none;
color: #333;
background: #DDD;
}
&:active, &:focus {
text-decoration: none;
}
i {
width: 20px;
color: #888;
margin-right: 23px;
}
}
}
.sidebar-subnav {
margin-left: 0px;
padding-left: 0px;
li {
line-height: 28px;
font-size: 12px;
list-style: none;
a {
padding: 5px 15px;
font-size: 12px;
padding-left: 20px;
}
}
}
@mixin expanded-sidebar {
.page-with-sidebar {
padding-left: 250px;
}
.sidebar-wrapper {
width: 250px;
position: absolute;
left: 250px;
height: 100%;
margin-left: -250px;
.nav-sidebar {
margin-top: 20px;
position: fixed;
top: 45px;
width: 250px;
}
}
.content-wrapper {
padding: 20px;
border-left: 1px solid #EAEAEA;
}
}
@mixin folded-sidebar {
.page-with-sidebar {
padding-left: 50px;
}
.sidebar-wrapper {
width: 52px;
position: absolute;
left: 50px;
height: 100%;
margin-left: -50px;
.nav-sidebar {
margin-top: 20px;
position: fixed;
top: 45px;
width: 52px;
li a {
padding-left: 18px;
font-size: 14px;
padding: 10px 15px;
text-align: center;
& > span {
display: none;
}
}
}
}
}
@media (max-width: $screen-sm-max) {
@include folded-sidebar;
}
@media(min-width: $screen-sm-max) {
@include expanded-sidebar;
}
...@@ -17,19 +17,6 @@ ...@@ -17,19 +17,6 @@
@include border-radius(0); @include border-radius(0);
tr { tr {
td, th {
padding: 8px 10px;
line-height: 20px;
}
th {
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid #CCC !important;
}
td {
border-color: #F1F1F1 !important;
border-bottom: 1px solid;
}
&:hover { &:hover {
td { td {
background: $hover; background: $hover;
......
...@@ -37,13 +37,3 @@ ...@@ -37,13 +37,3 @@
margin: 0 8px; margin: 0 8px;
} }
.votes-holder {
float: right;
width: 250px;
@media (max-width: $screen-xs-max) {
width: 100%;
margin-top: 5px;
margin-bottom: 10px;
}
}
...@@ -9,17 +9,15 @@ ...@@ -9,17 +9,15 @@
.navbar-inner { .navbar-inner {
background: #F1F1F1; background: #F1F1F1;
border-bottom: 1px solid #DDD; border-bottom: 1px solid #DDD;
.app_logo {
background-color: #DDD;
}
.nav > li > a { .nav > li > a {
color: $style_color; color: $style_color;
} }
.separator {
background: #F9F9F9;
border-left: 1px solid #DDD;
}
} }
} }
} }
.main-nav {
background: #FFF;
}
} }
...@@ -23,9 +23,8 @@ ...@@ -23,9 +23,8 @@
background-color: #436; background-color: #436;
} }
} }
.separator { .app_logo {
background: #436; background-color: #325;
border-left: 1px solid #659;
} }
.nav > li > a { .nav > li > a {
color: #98C; color: #98C;
......
...@@ -23,9 +23,8 @@ ...@@ -23,9 +23,8 @@
background-color: #272727; background-color: #272727;
} }
} }
.separator { .app_logo {
background: #272727; background-color: #222;
border-left: 1px solid #474747;
} }
} }
} }
......
...@@ -23,9 +23,8 @@ ...@@ -23,9 +23,8 @@
background-color: #373D47; background-color: #373D47;
} }
} }
.separator { .app_logo {
background: #373D47; background-color: #24272D;
border-left: 1px solid #575D67;
} }
.nav > li > a { .nav > li > a {
color: #979DA7; color: #979DA7;
......
...@@ -23,9 +23,8 @@ ...@@ -23,9 +23,8 @@
background-color: #018865; background-color: #018865;
} }
} }
.separator { .app_logo {
background: #018865; background-color: #017855;
border-left: 1px solid #11A885;
} }
.nav > li > a { .nav > li > a {
color: #ADC; color: #ADC;
......
...@@ -21,7 +21,7 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -21,7 +21,7 @@ class Admin::GroupsController < Admin::ApplicationController
def create def create
@group = Group.new(group_params) @group = Group.new(group_params)
@group.path = @group.name.dup.parameterize if @group.name @group.name = @group.path.dup unless @group.name
if @group.save if @group.save
@group.add_owner(current_user) @group.add_owner(current_user)
......
...@@ -245,4 +245,67 @@ class ApplicationController < ActionController::Base ...@@ -245,4 +245,67 @@ class ApplicationController < ActionController::Base
render_404 and return render_404 and return
end end
end end
def set_filters_params
params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@filter_params = params.dup
if @project
@filter_params[:project_id] = @project.id
elsif @group
@filter_params[:group_id] = @group.id
else
# TODO: this filter ignore issues/mr created in public or
# internal repos where you are not a member. Enable this filter
# or improve current implementation to filter only issues you
# created or assigned or mentioned
#@filter_params[:authorized_only] = true
unless @filter_params[:assignee_id]
@filter_params[:assignee_id] = current_user.id
end
end
@filter_params
end
def set_filter_values(collection)
assignee_id = @filter_params[:assignee_id]
author_id = @filter_params[:author_id]
milestone_id = @filter_params[:milestone_id]
@sort = @filter_params[:sort].try(:humanize)
@assignees = User.where(id: collection.pluck(:assignee_id))
@authors = User.where(id: collection.pluck(:author_id))
@milestones = Milestone.where(id: collection.pluck(:milestone_id))
if assignee_id.present? && !assignee_id.to_i.zero?
@assignee = @assignees.find_by(id: assignee_id)
end
if author_id.present? && !author_id.to_i.zero?
@author = @authors.find_by(id: author_id)
end
if milestone_id.present? && !milestone_id.to_i.zero?
@milestone = @milestones.find_by(id: milestone_id)
end
end
def get_issues_collection
set_filters_params
issues = IssuesFinder.new.execute(current_user, @filter_params)
set_filter_values(issues)
issues
end
def get_merge_requests_collection
set_filters_params
merge_requests = MergeRequestsFinder.new.execute(current_user, @filter_params)
set_filter_values(merge_requests)
merge_requests
end
end end
...@@ -3,8 +3,6 @@ class DashboardController < ApplicationController ...@@ -3,8 +3,6 @@ class DashboardController < ApplicationController
before_filter :load_projects, except: [:projects] before_filter :load_projects, except: [:projects]
before_filter :event_filter, only: :show before_filter :event_filter, only: :show
before_filter :default_filter, only: [:issues, :merge_requests]
def show def show
# Fetch only 30 projects. # Fetch only 30 projects.
...@@ -55,13 +53,13 @@ class DashboardController < ApplicationController ...@@ -55,13 +53,13 @@ class DashboardController < ApplicationController
end end
def merge_requests def merge_requests
@merge_requests = MergeRequestsFinder.new.execute(current_user, params) @merge_requests = get_merge_requests_collection
@merge_requests = @merge_requests.page(params[:page]).per(20) @merge_requests = @merge_requests.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project) @merge_requests = @merge_requests.preload(:author, :target_project)
end end
def issues def issues
@issues = IssuesFinder.new.execute(current_user, params) @issues = get_issues_collection
@issues = @issues.page(params[:page]).per(20) @issues = @issues.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project) @issues = @issues.preload(:author, :project)
...@@ -76,10 +74,4 @@ class DashboardController < ApplicationController ...@@ -76,10 +74,4 @@ class DashboardController < ApplicationController
def load_projects def load_projects
@projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = current_user.authorized_projects.sorted_by_activity.non_archived
end end
def default_filter
params[:scope] = 'assigned-to-me' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
params[:authorized_only] = true
end
end end
...@@ -11,8 +11,6 @@ class GroupsController < ApplicationController ...@@ -11,8 +11,6 @@ class GroupsController < ApplicationController
# Load group projects # Load group projects
before_filter :load_projects, except: [:new, :create, :projects, :edit, :update] before_filter :load_projects, except: [:new, :create, :projects, :edit, :update]
before_filter :default_filter, only: [:issues, :merge_requests]
layout :determine_layout layout :determine_layout
before_filter :set_title, only: [:new, :create] before_filter :set_title, only: [:new, :create]
...@@ -23,7 +21,7 @@ class GroupsController < ApplicationController ...@@ -23,7 +21,7 @@ class GroupsController < ApplicationController
def create def create
@group = Group.new(group_params) @group = Group.new(group_params)
@group.path = @group.name.dup.parameterize if @group.name @group.name = @group.path.dup unless @group.name
if @group.save if @group.save
@group.add_owner(current_user) @group.add_owner(current_user)
...@@ -49,13 +47,13 @@ class GroupsController < ApplicationController ...@@ -49,13 +47,13 @@ class GroupsController < ApplicationController
end end
def merge_requests def merge_requests
@merge_requests = MergeRequestsFinder.new.execute(current_user, params) @merge_requests = get_merge_requests_collection
@merge_requests = @merge_requests.page(params[:page]).per(20) @merge_requests = @merge_requests.page(params[:page]).per(20)
@merge_requests = @merge_requests.preload(:author, :target_project) @merge_requests = @merge_requests.preload(:author, :target_project)
end end
def issues def issues
@issues = IssuesFinder.new.execute(current_user, params) @issues = get_issues_collection
@issues = @issues.page(params[:page]).per(20) @issues = @issues.page(params[:page]).per(20)
@issues = @issues.preload(:author, :project) @issues = @issues.preload(:author, :project)
...@@ -150,18 +148,6 @@ class GroupsController < ApplicationController ...@@ -150,18 +148,6 @@ class GroupsController < ApplicationController
end end
end end
def default_filter
if params[:scope].blank?
if current_user
params[:scope] = 'assigned-to-me'
else
params[:scope] = 'all'
end
end
params[:state] = 'opened' if params[:state].blank?
params[:group_id] = @group.id
end
def group_params def group_params
params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock) params.require(:group).permit(:name, :description, :path, :avatar, :membership_lock)
end end
......
class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
before_filter :authenticate_user!
layout "profile"
def index
head :forbidden and return
end
def create
@application = Doorkeeper::Application.new(application_params)
if Doorkeeper.configuration.confirm_application_owner?
@application.owner = current_user
end
if @application.save
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
redirect_to oauth_application_url(@application)
else
render :new
end
end
def destroy
if @application.destroy
flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy])
end
redirect_to applications_profile_url
end
private
def set_application
@application = current_user.oauth_applications.find(params[:id])
end
rescue_from ActiveRecord::RecordNotFound do |exception|
render "errors/not_found", layout: "errors", status: 404
end
end
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
before_filter :authenticate_resource_owner!
layout "profile"
def new
if pre_auth.authorizable?
if skip_authorization? || matching_token?
auth = authorization.authorize
redirect_to auth.redirect_uri
else
render "doorkeeper/authorizations/new"
end
else
render "doorkeeper/authorizations/error"
end
end
# TODO: Handle raise invalid authorization
def create
redirect_or_render authorization.authorize
end
def destroy
redirect_or_render authorization.deny
end
private
def matching_token?
Doorkeeper::AccessToken.matching_token_for(pre_auth.client,
current_resource_owner.id,
pre_auth.scopes)
end
def redirect_or_render(auth)
if auth.redirectable?
redirect_to auth.redirect_uri
else
render json: auth.body, status: auth.status
end
end
def pre_auth
@pre_auth ||=
Doorkeeper::OAuth::PreAuthorization.new(Doorkeeper.configuration,
server.client_via_uid,
params)
end
def authorization
@authorization ||= strategy.request
end
def strategy
@strategy ||= server.authorization_request(pre_auth.response_type)
end
end
class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
layout "profile"
def destroy
Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner)
redirect_to applications_profile_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy])
end
end
...@@ -13,6 +13,11 @@ class ProfilesController < ApplicationController ...@@ -13,6 +13,11 @@ class ProfilesController < ApplicationController
def design def design
end end
def applications
@applications = current_user.oauth_applications
@authorized_tokens = current_user.oauth_authorized_tokens
end
def update def update
user_params.except!(:email) if @user.ldap_user? user_params.except!(:email) if @user.ldap_user?
......
...@@ -29,31 +29,4 @@ class Projects::ApplicationController < ApplicationController ...@@ -29,31 +29,4 @@ class Projects::ApplicationController < ApplicationController
redirect_to project_tree_path(@project, @ref), notice: "This action is not allowed unless you are on top of a branch" redirect_to project_tree_path(@project, @ref), notice: "This action is not allowed unless you are on top of a branch"
end end
end end
def set_filter_variables(collection)
params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@sort = params[:sort].humanize
assignee_id = params[:assignee_id]
author_id = params[:author_id]
milestone_id = params[:milestone_id]
if assignee_id.present? && !assignee_id.to_i.zero?
@assignee = @project.team.find(assignee_id)
end
if author_id.present? && !author_id.to_i.zero?
@author = @project.team.find(assignee_id)
end
if milestone_id.present? && !milestone_id.to_i.zero?
@milestone = @project.milestones.find(milestone_id)
end
@assignees = User.where(id: collection.pluck(:assignee_id))
@authors = User.where(id: collection.pluck(:author_id))
end
end end
...@@ -18,9 +18,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -18,9 +18,7 @@ class Projects::IssuesController < Projects::ApplicationController
def index def index
terms = params['issue_search'] terms = params['issue_search']
set_filter_variables(@project.issues) @issues = get_issues_collection
@issues = IssuesFinder.new.execute(current_user, params.merge(project_id: @project.id))
@issues = @issues.full_search(terms) if terms.present? @issues = @issues.full_search(terms) if terms.present?
@issues = @issues.page(params[:page]).per(20) @issues = @issues.page(params[:page]).per(20)
......
...@@ -17,9 +17,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -17,9 +17,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort] before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
def index def index
set_filter_variables(@project.merge_requests) @merge_requests = get_merge_requests_collection
@merge_requests = MergeRequestsFinder.new.execute(current_user, params.merge(project_id: @project.id))
@merge_requests = @merge_requests.page(params[:page]).per(20) @merge_requests = @merge_requests.page(params[:page]).per(20)
end end
......
...@@ -44,6 +44,9 @@ class ProjectsController < ApplicationController ...@@ -44,6 +44,9 @@ class ProjectsController < ApplicationController
def transfer def transfer
::Projects::TransferService.new(project, current_user, project_params).execute ::Projects::TransferService.new(project, current_user, project_params).execute
if @project.errors[:namespace_id].present?
flash[:alert] = @project.errors[:namespace_id].first
end
end end
def show def show
......
...@@ -114,6 +114,10 @@ module ApplicationHelper ...@@ -114,6 +114,10 @@ module ApplicationHelper
Gitlab::Theme.css_class_by_id(current_user.try(:theme_id)) Gitlab::Theme.css_class_by_id(current_user.try(:theme_id))
end end
def theme_type
Gitlab::Theme.type_css_class_by_id(current_user.try(:theme_id))
end
def user_color_scheme_class def user_color_scheme_class
COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user) COLOR_SCHEMES[current_user.try(:color_scheme_id)] if defined?(current_user)
end end
...@@ -271,4 +275,22 @@ module ApplicationHelper ...@@ -271,4 +275,22 @@ module ApplicationHelper
def promo_url def promo_url
'https://' + promo_host 'https://' + promo_host
end end
def page_filter_path(options={})
exist_opts = {
state: params[:state],
scope: params[:scope],
label_name: params[:label_name],
milestone_id: params[:milestone_id],
assignee_id: params[:assignee_id],
author_id: params[:author_id],
sort: params[:sort],
}
options = exist_opts.merge(options)
path = request.path
path << "?#{options.to_param}"
path
end
end end
module DashboardHelper module DashboardHelper
def filter_path(entity, options={})
exist_opts = {
state: params[:state],
scope: params[:scope],
project_id: params[:project_id],
}
options = exist_opts.merge(options)
path = request.path
path << "?#{options.to_param}"
path
end
def entities_per_project(project, entity) def entities_per_project(project, entity)
case entity.to_sym case entity.to_sym
when :issue then @issues.where(project_id: project.id) when :issue then @issues.where(project_id: project.id)
......
...@@ -117,4 +117,22 @@ module DiffHelper ...@@ -117,4 +117,22 @@ module DiffHelper
[comments_left, comments_right] [comments_left, comments_right]
end end
def inline_diff_btn
params_copy = params.dup
params_copy[:view] = 'inline'
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] != 'parallel' ? 'btn active' : 'btn') do
'Inline'
end
end
def parallel_diff_btn
params_copy = params.dup
params_copy[:view] = 'parallel'
link_to url_for(params_copy), id: "commit-diff-viewtype", class: (params[:view] == 'parallel' ? 'btn active' : 'btn') do
'Side-by-side'
end
end
end end
...@@ -21,15 +21,14 @@ module EventsHelper ...@@ -21,15 +21,14 @@ module EventsHelper
def event_filter_link(key, tooltip) def event_filter_link(key, tooltip)
key = key.to_s key = key.to_s
inactive = if @event_filter.active? key active = if @event_filter.active? key
nil 'active'
else end
'inactive'
end
content_tag :div, class: "filter_icon #{inactive}" do content_tag :li, class: "filter_icon #{active}" do
link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do link_to request.path, class: 'has_tooltip event_filter_link', id: "#{key}_event_filter", 'data-original-title' => tooltip do
content_tag :i, nil, class: icon_for_event[key] content_tag(:i, nil, class: icon_for_event[key]) +
content_tag(:span, ' ' + tooltip)
end end
end end
end end
......
...@@ -44,4 +44,14 @@ module GroupsHelper ...@@ -44,4 +44,14 @@ module GroupsHelper
path << "?#{options.to_param}" path << "?#{options.to_param}"
path path
end end
def group_settings_page?
if current_controller?('groups')
current_action?('edit') || current_action?('projects')
elsif current_controller?('ldap_group_links') || current_controller?('audit_events')
true
else
false
end
end
end end
...@@ -52,8 +52,11 @@ module NotesHelper ...@@ -52,8 +52,11 @@ module NotesHelper
discussion_id: discussion_id discussion_id: discussion_id
} }
button_tag '', class: 'btn add-diff-note js-add-diff-note-button', button_tag(class: 'btn add-diff-note js-add-diff-note-button',
data: data, title: 'Add a comment to this line' data: data,
title: 'Add a comment to this line') do
content_tag :i, nil, class: 'fa fa-comment-o'
end
end end
def link_to_reply_diff(note) def link_to_reply_diff(note)
......
...@@ -68,48 +68,6 @@ module ProjectsHelper ...@@ -68,48 +68,6 @@ module ProjectsHelper
project_nav_tabs.include? name project_nav_tabs.include? name
end end
def selected_label?(label_name)
params[:label_name].to_s.split(',').include?(label_name)
end
def labels_filter_path(label_name)
label_name =
if selected_label?(label_name)
params[:label_name].split(',').reject { |l| l == label_name }.join(',')
elsif params[:label_name].present?
"#{params[:label_name]},#{label_name}"
else
label_name
end
project_filter_path(label_name: label_name)
end
def label_filter_class(label_name)
if selected_label?(label_name)
'label-filter-item active'
else
'label-filter-item light'
end
end
def project_filter_path(options={})
exist_opts = {
state: params[:state],
scope: params[:scope],
label_name: params[:label_name],
milestone_id: params[:milestone_id],
assignee_id: params[:assignee_id],
sort: params[:sort],
}
options = exist_opts.merge(options)
path = request.path
path << "?#{options.to_param}"
path
end
def project_active_milestones def project_active_milestones
@project.milestones.active.order("due_date, title ASC") @project.milestones.active.order("due_date, title ASC")
end end
......
...@@ -28,6 +28,10 @@ module TabHelper ...@@ -28,6 +28,10 @@ module TabHelper
# nav_link(controller: [:tree, :refs]) { "Hello" } # nav_link(controller: [:tree, :refs]) { "Hello" }
# # => '<li class="active">Hello</li>' # # => '<li class="active">Hello</li>'
# #
# # Several paths
# nav_link(path: ['tree#show', 'profile#show']) { "Hello" }
# # => '<li class="active">Hello</li>'
#
# # Shorthand path # # Shorthand path
# nav_link(path: 'tree#show') { "Hello" } # nav_link(path: 'tree#show') { "Hello" }
# # => '<li class="active">Hello</li>' # # => '<li class="active">Hello</li>'
...@@ -38,25 +42,7 @@ module TabHelper ...@@ -38,25 +42,7 @@ module TabHelper
# #
# Returns a list item element String # Returns a list item element String
def nav_link(options = {}, &block) def nav_link(options = {}, &block)
if path = options.delete(:path) klass = active_nav_link?(options) ? 'active' : ''
if path.respond_to?(:each)
c = path.map { |p| p.split('#').first }
a = path.map { |p| p.split('#').last }
else
c, a, _ = path.split('#')
end
else
c = options.delete(:controller)
a = options.delete(:action)
end
if c && a
# When given both options, make sure BOTH are active
klass = current_controller?(*c) && current_action?(*a) ? 'active' : ''
else
# Otherwise check EITHER option
klass = current_controller?(*c) || current_action?(*a) ? 'active' : ''
end
# Add our custom class into the html_options, which may or may not exist # Add our custom class into the html_options, which may or may not exist
# and which may or may not already have a :class key # and which may or may not already have a :class key
...@@ -72,6 +58,34 @@ module TabHelper ...@@ -72,6 +58,34 @@ module TabHelper
end end
end end
def active_nav_link?(options)
if path = options.delete(:path)
unless path.respond_to?(:each)
path = [path]
end
path.any? do |single_path|
current_path?(single_path)
end
else
c = options.delete(:controller)
a = options.delete(:action)
if c && a
# When given both options, make sure BOTH are true
current_controller?(*c) && current_action?(*a)
else
# Otherwise check EITHER option
current_controller?(*c) || current_action?(*a)
end
end
end
def current_path?(path)
c, a, _ = path.split('#')
current_controller?(c) && current_action?(a)
end
def project_tab_class def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project) return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
......
...@@ -53,13 +53,41 @@ module TreeHelper ...@@ -53,13 +53,41 @@ module TreeHelper
File.join(*args) File.join(*args)
end end
def allowed_tree_edit? def allowed_tree_edit?(project = nil, ref = nil)
return false unless @repository.branch_names.include?(@ref) project ||= @project
ref ||= @ref
return false unless project.repository.branch_names.include?(ref)
if @project.protected_branch? @ref if project.protected_branch? ref
can?(current_user, :push_code_to_protected_branches, @project) can?(current_user, :push_code_to_protected_branches, project)
else else
can?(current_user, :push_code, @project) can?(current_user, :push_code, project)
end
end
def edit_blob_link(project, ref, path, options = {})
blob =
begin
project.repository.blob_at(ref, path)
rescue
nil
end
if blob && blob.text?
text = 'Edit'
after = options[:after] || ''
from_mr = options[:from_merge_request_id]
link_opts = {}
link_opts[:from_merge_request_id] = from_mr if from_mr
cls = 'btn btn-small'
if allowed_tree_edit?(project, ref)
link_to text, project_edit_tree_path(project, tree_join(ref, path),
link_opts), class: cls
else
content_tag :span, text, class: cls + ' disabled'
end + after.html_safe
else
''
end end
end end
......
...@@ -106,6 +106,7 @@ class User < ActiveRecord::Base ...@@ -106,6 +106,7 @@ class User < ActiveRecord::Base
has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event" has_many :recent_events, -> { order "id DESC" }, foreign_key: :author_id, class_name: "Event"
has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue"
has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest"
has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy
# #
...@@ -575,4 +576,8 @@ class User < ActiveRecord::Base ...@@ -575,4 +576,8 @@ class User < ActiveRecord::Base
namespaces += masters_groups namespaces += masters_groups
end end
end end
def oauth_authorized_tokens
Doorkeeper::AccessToken.where(resource_owner_id: self.id, revoked_at: nil)
end
end end
module Oauth2::AccessTokenValidationService
# Results:
VALID = :valid
EXPIRED = :expired
REVOKED = :revoked
INSUFFICIENT_SCOPE = :insufficient_scope
class << self
def validate(token, scopes: [])
if token.expired?
return EXPIRED
elsif token.revoked?
return REVOKED
elsif !self.sufficent_scope?(token, scopes)
return INSUFFICIENT_SCOPE
else
return VALID
end
end
protected
# True if the token's scope is a superset of required scopes,
# or the required scopes is empty.
def sufficent_scope?(token, scopes)
if scopes.blank?
# if no any scopes required, the scopes of token is sufficient.
return true
else
# If there are scopes required, then check whether
# the set of authorized scopes is a superset of the set of required scopes
required_scopes = Set.new(scopes)
authorized_scopes = Set.new(token.scopes)
return authorized_scopes >= required_scopes
end
end
end
end
\ No newline at end of file
...@@ -12,12 +12,17 @@ module Projects ...@@ -12,12 +12,17 @@ module Projects
@project.visibility_level = default_features.visibility_level @project.visibility_level = default_features.visibility_level
end end
# Parametrize path for project # Set project name from path
# if @project.name.present? && @project.path.present?
# Ex. # if both name and path set - everything is ok
# 'GitLab HQ'.parameterize => "gitlab-hq" elsif @project.path.present?
# # Set project name from path
@project.path = @project.name.dup.parameterize unless @project.path.present? @project.name = @project.path.dup
elsif @project.name.present?
# For compatibility - set path from name
# TODO: remove this in 8.0
@project.path = @project.name.dup.parameterize
end
# get namespace id # get namespace id
namespace_id = params[:namespace_id] namespace_id = params[:namespace_id]
......
...@@ -21,18 +21,6 @@ ...@@ -21,18 +21,6 @@
= link_to 'Cancel', admin_groups_path, class: "btn btn-cancel" = link_to 'Cancel', admin_groups_path, class: "btn btn-cancel"
- else - else
.form-group.group_name_holder
= f.label :path, class: 'control-label' do
%span Group path
.col-sm-10
= f.text_field :path, placeholder: "example-group", class: "form-control danger"
.bs-callout.bs-callout-danger
%ul
%li Changing group path can have unintended side effects.
%li Renaming group path will rename directory for all related projects
%li It will change web url for access group and group projects.
%li It will change the git path to repositories under this group.
.form-actions .form-actions
= f.submit 'Save changes', class: "btn btn-primary" = f.submit 'Save changes', class: "btn btn-primary"
= link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel" = link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel"
......
.row %h3.page-title Group Audit Events
.col-md-2 %p.light Events in #{@group.name}
= render 'groups/settings_nav'
.col-md-10 = render 'event_table', events: @events
%h3.page-title Group Audit Events
%p.light Events in #{@group.name}
= render 'event_table', events: @events
.panel.panel-default .panel.panel-default
.panel-heading.clearfix .panel-heading.clearfix
= search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' .input-group
- if current_user.can_create_group? = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
= link_to new_group_path, class: "btn btn-new pull-right" do - if current_user.can_create_group?
%i.fa.fa-plus .input-group-addon
New group = link_to new_group_path, class: "" do
%strong New group
%ul.well-list.dash-list %ul.well-list.dash-list
- groups.each do |group| - groups.each do |group|
%li.group-row %li.group-row
......
.panel.panel-default .panel.panel-default
.panel-heading.clearfix .panel-heading.clearfix
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' .input-group
- if current_user.can_create_project? = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
= link_to new_project_path, class: "btn btn-new pull-right" do - if current_user.can_create_project?
%i.fa.fa-plus .input-group-addon
New project = link_to new_project_path, class: "" do
%strong New project
%ul.well-list.dash-list %ul.well-list.dash-list
- projects.each do |project| - projects.each do |project|
......
...@@ -15,11 +15,4 @@ ...@@ -15,11 +15,4 @@
= render "groups", groups: @groups = render "groups", groups: @groups
.prepend-top-20 .prepend-top-20
%span.rss-icon = render 'shared/promo'
= link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
%strong
%i.fa.fa-rss
News Feed
%hr
= render 'shared/promo'
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
List all issues from all projects you have access to. List all issues from all projects you have access to.
%hr %hr
.row .append-bottom-20
.fixed.sidebar-expand-button.hidden-lg.hidden-md = render 'shared/issuable_filter'
%i.fa.fa-list.fa-2x = render 'shared/issues'
.col-md-3.responsive-side
= render 'shared/filter', entity: 'issue'
.col-md-9
= render 'shared/issues'
...@@ -5,10 +5,6 @@ ...@@ -5,10 +5,6 @@
%p.light %p.light
List all merge requests from all projects you have access to. List all merge requests from all projects you have access to.
%hr %hr
.row .append-bottom-20
.fixed.sidebar-expand-button.hidden-lg.hidden-md = render 'shared/issuable_filter'
%i.fa.fa-list.fa-2x = render 'shared/merge_requests'
.col-md-3.responsive-side
= render 'shared/filter', entity: 'merge_request'
.col-md-9
= render 'shared/merge_requests'
...@@ -38,17 +38,19 @@ ...@@ -38,17 +38,19 @@
= link_to project_path(project), class: dom_class(project) do = link_to project_path(project), class: dom_class(project) do
= project.name_with_namespace = project.name_with_namespace
- if project.forked_from_project
&nbsp;
%small
%i.fa.fa-code-fork
Forked from:
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
- if current_user.can_leave_project?(project) - if current_user.can_leave_project?(project)
.pull-right .pull-right
= link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do = link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do
%i.fa.fa-sign-out %i.fa.fa-sign-out
Leave Leave
- if project.forked_from_project
%small.pull-right
%i.fa.fa-code-fork
Forked from:
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
.project-info .project-info
.pull-right .pull-right
- if project.archived? - if project.archived?
......
- submit_btn_css ||= 'btn btn-link btn-remove btn-small'
= form_tag oauth_application_path(application) do
%input{:name => "_method", :type => "hidden", :value => "delete"}/
= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
\ No newline at end of file
= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f|
- if application.errors.any?
.alert.alert-danger{"data-alert" => ""}
%p Whoops! Check your form for possible errors
= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do
= f.label :name, class: 'col-sm-2 control-label'
.col-sm-10
= f.text_field :name, class: 'form-control'
= doorkeeper_errors_for application, :name
= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do
= f.label :redirect_uri, class: 'col-sm-2 control-label'
.col-sm-10
= f.text_area :redirect_uri, class: 'form-control'
= doorkeeper_errors_for application, :redirect_uri
%span.help-block
Use one line per URI
- if Doorkeeper.configuration.native_redirect_uri
%span.help-block
Use
%code= Doorkeeper.configuration.native_redirect_uri
for local tests
.form-actions
= f.submit 'Submit', class: "btn btn-primary wide"
= link_to "Cancel", applications_profile_path, class: "btn btn-default"
%h3.page-title Edit application
= render 'form', application: @application
\ No newline at end of file
%h3.page-title Your applications
%p= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success'
%table.table.table-striped
%thead
%tr
%th Name
%th Callback URL
%th
%th
%tbody
- @applications.each do |application|
%tr{:id => "application_#{application.id}"}
%td= link_to application.name, oauth_application_path(application)
%td= application.redirect_uri
%td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link'
%td= render 'delete_form', application: application
\ No newline at end of file
%h3.page-title New application
= render 'form', application: @application
\ No newline at end of file
%h3.page-title
Application: #{@application.name}
%table.table
%tr
%td
Application Id
%td
%code#application_id= @application.uid
%tr
%td
Secret:
%td
%code#secret= @application.secret
%tr
%td
Callback url
%td
- @application.redirect_uri.split.each do |uri|
%div
%span.monospace= uri
.form-actions
= link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left'
= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
%h3.page-title An error has occurred
%main{:role => "main"}
%pre= @pre_auth.error_response.body[:error_description]
\ No newline at end of file
%h3.page-title Authorize required
%main{:role => "main"}
%p.h4
Authorize
%strong.text-info= @pre_auth.client.name
to use your account?
- if @pre_auth.scopes
#oauth-permissions
%p This application will be able to:
%ul.text-info
- @pre_auth.scopes.each do |scope|
%li= t scope, scope: [:doorkeeper, :scopes]
%hr/
.actions
= form_tag oauth_authorization_path, method: :post do
= hidden_field_tag :client_id, @pre_auth.client.uid
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
= hidden_field_tag :state, @pre_auth.state
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= submit_tag "Authorize", class: "btn btn-success wide pull-left"
= form_tag oauth_authorization_path, method: :delete do
= hidden_field_tag :client_id, @pre_auth.client.uid
= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri
= hidden_field_tag :state, @pre_auth.state
= hidden_field_tag :response_type, @pre_auth.response_type
= hidden_field_tag :scope, @pre_auth.scope
= submit_tag "Deny", class: "btn btn-danger prepend-left-10"
\ No newline at end of file
%h3.page-title Authorization code:
%main{:role => "main"}
%code#authorization_code= params[:code]
\ No newline at end of file
- submit_btn_css ||= 'btn btn-link btn-remove'
= form_tag oauth_authorized_application_path(application) do
%input{:name => "_method", :type => "hidden", :value => "delete"}/
= submit_tag 'Revoke', onclick: "return confirm('Are you sure?')", class: 'btn btn-link btn-remove btn-small'
\ No newline at end of file
%header.page-header
%h1 Your authorized applications
%main{:role => "main"}
%table.table.table-striped
%thead
%tr
%th Application
%th Created At
%th
%th
%tbody
- @applications.each do |application|
%tr
%td= application.name
%td= application.created_at.strftime('%Y-%m-%d %H:%M:%S')
%td= render 'delete_form', application: application
\ No newline at end of file
%ul.nav.nav-pills.nav-stacked.nav-stacked-menu %ul.sidebar-subnav
= nav_link(path: 'groups#edit') do = nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group) do = link_to edit_group_path(@group) do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
......
.row .panel.panel-default
.col-md-2 .panel-heading
= render 'settings_nav' %strong= @group.name
.col-md-10 group settings:
.panel.panel-default .panel-body
.panel-heading = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f|
%strong= @group.name - if @group.errors.any?
group settings: .alert.alert-danger
.panel-body %span= @group.errors.full_messages.first
= form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| = render 'shared/group_form', f: f
- if @group.errors.any?
.alert.alert-danger
%span= @group.errors.full_messages.first
= render 'shared/group_form', f: f
.form-group .form-group
.col-sm-2 .col-sm-2
.col-sm-10 .col-sm-10
= image_tag group_icon(@group.to_param), alt: '', class: 'avatar s160' = image_tag group_icon(@group.to_param), alt: '', class: 'avatar s160'
%p.light %p.light
- if @group.avatar? - if @group.avatar?
You can change your group avatar here You can change your group avatar here
- else - else
You can upload a group avatar here You can upload a group avatar here
= render 'shared/choose_group_avatar_button', f: f = render 'shared/choose_group_avatar_button', f: f
- if @group.avatar? - if @group.avatar?
%hr
= link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
.form-group
%hr %hr
= f.label :name, class: 'control-label' do = link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
Member lock
.col-sm-10 .form-group
.checkbox %hr
= f.check_box :membership_lock = f.label :name, class: 'control-label' do
%span.descr Prevent adding new members to project membership within this group Member lock
.col-sm-10
.checkbox
= f.check_box :membership_lock
%span.descr Prevent adding new members to project membership within this group
.form-actions .form-actions
= f.submit 'Save group', class: "btn btn-save" = f.submit 'Save group', class: "btn btn-save"
.panel.panel-danger .panel.panel-danger
.panel-heading Remove group .panel-heading Remove group
.panel-body .panel-body
%p %p
Removing group will cause all child projects and resources to be removed. Removing group will cause all child projects and resources to be removed.
%br %br
%strong Removed group can not be restored! %strong Removed group can not be restored!
= link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove" = link_to 'Remove Group', @group, data: {confirm: 'Removed group can not be restored! Are you sure?'}, method: :delete, class: "btn btn-remove"
...@@ -9,10 +9,6 @@ ...@@ -9,10 +9,6 @@
To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page. To see all issues you should visit #{link_to 'dashboard', issues_dashboard_path} page.
%hr %hr
.row .append-bottom-20
.fixed.sidebar-expand-button.hidden-lg.hidden-md = render 'shared/issuable_filter'
%i.fa.fa-list.fa-2x = render 'shared/issues'
.col-md-3.responsive-side
= render 'shared/filter', entity: 'issue'
.col-md-9
= render 'shared/issues'
.row %h3.page-title Linked LDAP groups
.col-md-2= render 'groups/settings_nav' = render 'ldap_group_links/form', group: @group
.col-md-10 = render 'ldap_group_links/ldap_group_links', group: @group
%h3.page-title Linked LDAP groups
= render 'ldap_group_links/form', group: @group
= render 'ldap_group_links/ldap_group_links', group: @group
...@@ -8,10 +8,6 @@ ...@@ -8,10 +8,6 @@
- if current_user - if current_user
To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page. To see all merge requests you should visit #{link_to 'dashboard', merge_requests_dashboard_path} page.
%hr %hr
.row .append-bottom-20
.fixed.sidebar-expand-button.hidden-lg.hidden-md = render 'shared/issuable_filter'
%i.fa.fa-list.fa-2x = render 'shared/merge_requests'
.col-md-3.responsive-side
= render 'shared/filter', entity: 'merge_request'
.col-md-9
= render 'shared/merge_requests'
.row .panel.panel-default
.col-md-2 .panel-heading
= render 'settings_nav' %strong= @group.name
.col-md-10 projects:
.panel.panel-default - if can? current_user, :manage_group, @group
.panel-heading .panel-head-actions
%strong= @group.name = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do
projects: %i.fa.fa-plus
- if can? current_user, :manage_group, @group New Project
.panel-head-actions %ul.well-list
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do - @projects.each do |project|
%i.fa.fa-plus %li
New Project .list-item-name
%ul.well-list = visibility_level_icon(project.visibility_level)
- @projects.each do |project| %strong= link_to project.name_with_namespace, project
%li %span.label.label-gray
.list-item-name = repository_size(project)
= visibility_level_icon(project.visibility_level) .pull-right
%strong= link_to project.name_with_namespace, project = link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
%span.label.label-gray = link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= repository_size(project) = link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-small btn-remove"
.pull-right - if @projects.blank?
= link_to 'Members', project_team_index_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small" .nothing-here-block This group has no projects yet
= link_to 'Edit', edit_project_path(project), id: "edit_#{dom_id(project)}", class: "btn btn-small"
= link_to 'Remove', project, data: { confirm: remove_project_message(project)}, method: :delete, class: "btn btn-small btn-remove"
- if @projects.blank?
.nothing-here-block This group has no projects yet
= paginate @projects, theme: "gitlab" = paginate @projects, theme: "gitlab"
.dashboard .dashboard
%section.activities.col-md-8.hidden-sm.hidden-xs %div
- if current_user = image_tag group_icon(@group.path), class: "avatar s90"
= render "events/event_last_push", event: @last_push .clearfix
= link_to dashboard_path, class: 'btn btn-tiny' do %h2
&larr; To dashboard = @group.name
&nbsp; - if @group.description.present?
%span.cgray %p
Currently you are only seeing events from the = escaped_autolink(@group.description)
= @group.name %hr
group .row
%hr %section.activities.col-md-8.hidden-sm.hidden-xs
= render 'shared/event_filter' - if current_user
- if @events.any? = render "events/event_last_push", event: @last_push
.content_list = render 'shared/event_filter'
- else - if @events.any?
.nothing-here-block Project activity will be displayed here .content_list
= spinner - else
%aside.side.col-md-4 .nothing-here-block Project activity will be displayed here
.light-well.append-bottom-20 = spinner
= image_tag group_icon(@group.path), class: "avatar s90" %aside.side.col-md-4
.clearfix.light = render "projects", projects: @projects
%h3.page-title %br
= @group.name = render "shared_projects", projects: @shared_projects
- if @group.description.present?
%p
= escaped_autolink(@group.description)
= render "projects", projects: @projects
%br
= render "shared_projects", projects: @shared_projects
- if current_user
.prepend-top-20
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
%strong
%i.fa.fa-rss
News Feed
%hr
= render 'shared/promo'
...@@ -2,3 +2,7 @@ ...@@ -2,3 +2,7 @@
.broadcast-message{ style: broadcast_styling(broadcast_message) } .broadcast-message{ style: broadcast_styling(broadcast_message) }
%i.fa.fa-bullhorn %i.fa.fa-bullhorn
= broadcast_message.message = broadcast_message.message
:css
.sidebar-wrapper .nav-sidebar {
margin-top: 58px;
}
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
.navbar-inner .navbar-inner
.container .container
%div.app_logo %div.app_logo
%span.separator
= link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do = link_to root_path, class: "home has_bottom_tooltip", title: "Dashboard" do
%h1 GITLAB %h1 GITLAB
%span.separator
%h1.title= title %h1.title= title
%button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
......
- if defined?(sidebar)
.page-with-sidebar
.sidebar-wrapper
= render(sidebar)
.content-wrapper
.container-fluid
.content
= render "layouts/flash"
.clearfix
= yield
- else
.container.navless-container
.content
= yield
= yield :embedded_scripts
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: "Admin area" = render "layouts/head", title: "Admin area"
%body{class: "#{app_theme} admin", :'data-page' => body_data_page} %body{class: "#{app_theme} #{theme_type} admin", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: "Admin area" = render "layouts/head_panel", title: "Admin area"
%nav.main-nav.navbar-collapse.collapse = render 'layouts/page', sidebar: 'layouts/nav/admin'
.container= render 'layouts/nav/admin'
.container
.content
= render "layouts/flash"
= yield
= yield :embedded_scripts
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: "Dashboard" = render "layouts/head", title: "Dashboard"
%body{class: "#{app_theme} application", :'data-page' => body_data_page } %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page }
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: "Dashboard" = render "layouts/head_panel", title: "Dashboard"
%nav.main-nav.navbar-collapse.collapse = render 'layouts/page', sidebar: 'layouts/nav/dashboard'
.container= render 'layouts/nav/dashboard'
.container
.content
= render "layouts/flash"
= yield
!!!
%html
%head
%meta{:charset => "utf-8"}
%meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}
%title Doorkeeper
= stylesheet_link_tag "doorkeeper/admin/application"
= csrf_meta_tags
%body
.navbar.navbar-inverse.navbar-fixed-top{:role => "navigation"}
.container
.navbar-header
= link_to 'OAuth2 Provider', oauth_applications_path, class: 'navbar-brand'
%ul.nav.navbar-nav
= content_tag :li, class: "#{'active' if request.path == oauth_applications_path}" do
= link_to 'Applications', oauth_applications_path
.container
- if flash[:notice].present?
.alert.alert-info
= flash[:notice]
= yield
\ No newline at end of file
!!!
%html
%head
%title OAuth authorize required
%meta{:charset => "utf-8"}
%meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}
%meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"}
= stylesheet_link_tag "doorkeeper/application"
= csrf_meta_tags
%body
#container
- if flash[:notice].present?
.alert.alert-info
= flash[:notice]
= yield
\ No newline at end of file
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: "Error" = render "layouts/head", title: "Error"
%body{class: "#{app_theme} application"} %body{class: "#{app_theme} #{theme_type} application"}
= render "layouts/head_panel", title: "" if current_user = render "layouts/head_panel", title: "" if current_user
.container.navless-container .container.navless-container
= render "layouts/flash" = render "layouts/flash"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: page_title = render "layouts/head", title: page_title
%body{class: "#{app_theme} application", :'data-page' => body_data_page} %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
- if current_user - if current_user
= render "layouts/head_panel", title: page_title = render "layouts/head_panel", title: page_title
......
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: group_head_title = render "layouts/head", title: group_head_title
%body{class: "#{app_theme} application", :'data-page' => body_data_page} %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: "group: #{@group.name}" = render "layouts/head_panel", title: @group.name
%nav.main-nav.navbar-collapse.collapse = render 'layouts/page', sidebar: 'layouts/nav/group'
.container= render 'layouts/nav/group'
.container
.content
= render "layouts/flash"
= yield
%ul %ul.nav.nav-sidebar
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to admin_root_path, title: "Stats" do = link_to admin_root_path, title: "Stats" do
Overview %i.fa.fa-dashboard
%span
Overview
= nav_link(controller: :projects) do = nav_link(controller: :projects) do
= link_to "Projects", admin_projects_path = link_to admin_projects_path do
%i.fa.fa-cube
%span
Projects
= nav_link(controller: :users) do = nav_link(controller: :users) do
= link_to "Users", admin_users_path = link_to admin_users_path do
%i.fa.fa-users
%span
Users
= nav_link(controller: :groups) do = nav_link(controller: :groups) do
= link_to "Groups", admin_groups_path = link_to admin_groups_path do
%i.fa.fa-group
%span
Groups
= nav_link(controller: :logs) do = nav_link(controller: :logs) do
= link_to "Logs", admin_logs_path = link_to admin_logs_path do
%i.fa.fa-file-text
%span
Logs
= nav_link(controller: :broadcast_messages) do = nav_link(controller: :broadcast_messages) do
= link_to "Messages", admin_broadcast_messages_path = link_to admin_broadcast_messages_path do
%i.fa.fa-bullhorn
%span
Messages
= nav_link(controller: :hooks) do = nav_link(controller: :hooks) do
= link_to "Hooks", admin_hooks_path = link_to admin_hooks_path do
%i.fa.fa-external-link
%span
Hooks
= nav_link(controller: :background_jobs) do = nav_link(controller: :background_jobs) do
= link_to "Background Jobs", admin_background_jobs_path = link_to admin_background_jobs_path do
%i.fa.fa-cog
%span
Background Jobs
= nav_link(controller: :appearances) do = nav_link(controller: :appearances) do
= link_to "Appearance", admin_appearances_path = link_to admin_appearances_path do
%i.fa.fa-image
%span
Appearance
%ul %ul.nav.nav-sidebar
= nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do = nav_link(path: 'dashboard#show', html_options: {class: 'home'}) do
= link_to root_path, title: 'Home', class: 'shortcuts-activity' do = link_to root_path, title: 'Home', class: 'shortcuts-activity' do
Activity %i.fa.fa-dashboard
%span
Activity
= nav_link(path: 'dashboard#projects') do = nav_link(path: 'dashboard#projects') do
= link_to projects_dashboard_path, class: 'shortcuts-projects' do = link_to projects_dashboard_path, class: 'shortcuts-projects' do
Projects %i.fa.fa-cube
%span
Projects
= nav_link(path: 'dashboard#issues') do = nav_link(path: 'dashboard#issues') do
= link_to issues_dashboard_path, class: 'shortcuts-issues' do = link_to issues_dashboard_path, class: 'shortcuts-issues' do
Issues %i.fa.fa-exclamation-circle
%span.count= current_user.assigned_issues.opened.count %span
Issues
%span.count= current_user.assigned_issues.opened.count
= nav_link(path: 'dashboard#merge_requests') do = nav_link(path: 'dashboard#merge_requests') do
= link_to merge_requests_dashboard_path, class: 'shortcuts-merge_requests' do = link_to merge_requests_dashboard_path, class: 'shortcuts-merge_requests' do
Merge Requests %i.fa.fa-tasks
%span.count= current_user.assigned_merge_requests.opened.count %span
Merge Requests
%span.count= current_user.assigned_merge_requests.opened.count
= nav_link(controller: :help) do = nav_link(controller: :help) do
= link_to "Help", help_path = link_to help_path do
%i.fa.fa-question-circle
%span
Help
%ul %ul.nav.nav-sidebar
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: "Home" do = link_to group_path(@group), title: "Home" do
Activity %i.fa.fa-dashboard
= nav_link(controller: [:group, :milestones]) do %span
= link_to group_milestones_path(@group) do Activity
Milestones - if current_user
= nav_link(controller: [:group, :milestones]) do
= link_to group_milestones_path(@group) do
%i.fa.fa-clock-o
%span
Milestones
= nav_link(path: 'groups#issues') do = nav_link(path: 'groups#issues') do
= link_to issues_group_path(@group) do = link_to issues_group_path(@group) do
Issues %i.fa.fa-exclamation-circle
- if current_user %span
%span.count= current_user.assigned_issues.opened.of_group(@group).count Issues
- if current_user
%span.count= Issue.opened.of_group(@group).count
= nav_link(path: 'groups#merge_requests') do = nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group) do = link_to merge_requests_group_path(@group) do
Merge Requests %i.fa.fa-tasks
- if current_user %span
%span.count= current_user.cared_merge_requests.opened.of_group(@group).count Merge Requests
- if current_user
%span.count= MergeRequest.opened.of_group(@group).count
= nav_link(path: 'groups#members') do = nav_link(path: 'groups#members') do
= link_to "Members", members_group_path(@group) = link_to members_group_path(@group) do
%i.fa.fa-users
%span
Members
- if can?(current_user, :manage_group, @group) - if can?(current_user, :manage_group, @group)
= nav_link(path: 'groups#edit') do = nav_link(html_options: { class: "#{"active" if group_settings_page?} separate-item" }) do
= link_to edit_group_path(@group), class: "tab " do = link_to edit_group_path(@group), class: "tab no-highlight" do
Settings %i.fa.fa-cogs
%span
Settings
%i.fa.fa-angle-down
- if group_settings_page?
= render 'groups/settings_nav'
%ul %ul.nav.nav-sidebar
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: "Profile" do = link_to profile_path, title: "Profile" do
Profile %i.fa.fa-user
%span
Profile
= nav_link(controller: :accounts) do = nav_link(controller: :accounts) do
= link_to "Account", profile_account_path = link_to profile_account_path do
%i.fa.fa-gear
Account
= nav_link(path: ['profiles#applications', 'applications#edit', 'applications#show', 'applications#new']) do
= link_to applications_profile_path do
%i.fa.fa-cloud
%span
Applications
= nav_link(controller: :emails) do = nav_link(controller: :emails) do
= link_to profile_emails_path do = link_to profile_emails_path do
Emails %i.fa.fa-envelope-o
%span.count= current_user.emails.count + 1 %span
Emails
%span.count= current_user.emails.count + 1
- unless current_user.ldap_user? - unless current_user.ldap_user?
= nav_link(controller: :passwords) do = nav_link(controller: :passwords) do
= link_to "Password", edit_profile_password_path = link_to edit_profile_password_path do
%i.fa.fa-lock
%span
Password
= nav_link(controller: :notifications) do = nav_link(controller: :notifications) do
= link_to "Notifications", profile_notifications_path = link_to profile_notifications_path do
%i.fa.fa-inbox
%span
Notifications
= nav_link(controller: :keys) do = nav_link(controller: :keys) do
= link_to profile_keys_path do = link_to profile_keys_path do
SSH Keys %i.fa.fa-key
%span.count= current_user.keys.count %span
SSH Keys
%span.count= current_user.keys.count
= nav_link(path: 'profiles#design') do = nav_link(path: 'profiles#design') do
= link_to "Design", design_profile_path = link_to design_profile_path do
%i.fa.fa-image
%span
Design
= nav_link(controller: :groups) do = nav_link(controller: :groups) do
= link_to "Groups", profile_groups_path = link_to profile_groups_path do
%i.fa.fa-group
%span
Groups
= nav_link(path: 'profiles#history') do = nav_link(path: 'profiles#history') do
= link_to "History", history_profile_path = link_to history_profile_path do
%i.fa.fa-history
%span
History
%ul.project-navigation %ul.project-navigation.nav.nav-sidebar
= nav_link(path: 'projects#show', html_options: {class: "home"}) do = nav_link(path: 'projects#show', html_options: {class: "home"}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
Project %i.fa.fa-dashboard
%span
Project
- if project_nav_tab? :files - if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree)) do = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do
= link_to 'Files', project_tree_path(@project, @ref || @repository.root_ref), class: 'shortcuts-tree' = link_to project_tree_path(@project, @ref || @repository.root_ref), class: 'shortcuts-tree' do
%i.fa.fa-files-o
%span
Files
- if project_nav_tab? :commits - if project_nav_tab? :commits
= nav_link(controller: %w(commit commits compare repositories tags branches)) do = nav_link(controller: %w(commit commits compare repositories tags branches)) do
= link_to "Commits", project_commits_path(@project, @ref || @repository.root_ref), class: 'shortcuts-commits' = link_to project_commits_path(@project, @ref || @repository.root_ref), class: 'shortcuts-commits' do
%i.fa.fa-history
%span
Commits
- if project_nav_tab? :network - if project_nav_tab? :network
= nav_link(controller: %w(network)) do = nav_link(controller: %w(network)) do
= link_to "Network", project_network_path(@project, @ref || @repository.root_ref), class: 'shortcuts-network' = link_to project_network_path(@project, @ref || @repository.root_ref), class: 'shortcuts-network' do
%i.fa.fa-code-fork
%span
Network
- if project_nav_tab? :graphs - if project_nav_tab? :graphs
= nav_link(controller: %w(graphs)) do = nav_link(controller: %w(graphs)) do
= link_to "Graphs", project_graph_path(@project, @ref || @repository.root_ref), class: 'shortcuts-graphs' = link_to project_graph_path(@project, @ref || @repository.root_ref), class: 'shortcuts-graphs' do
%i.fa.fa-area-chart
%span
Graphs
- if project_nav_tab? :issues - if project_nav_tab? :issues
= nav_link(controller: %w(issues milestones labels)) do = nav_link(controller: %w(issues milestones labels)) do
= link_to url_for_project_issues, class: 'shortcuts-issues' do = link_to url_for_project_issues, class: 'shortcuts-issues' do
Issues %i.fa.fa-exclamation-circle
- if @project.used_default_issues_tracker? %span
%span.count.issue_counter= @project.issues.opened.count Issues
- if @project.used_default_issues_tracker?
%span.count.issue_counter= @project.issues.opened.count
- if project_nav_tab? :merge_requests - if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do = nav_link(controller: :merge_requests) do
= link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests' do = link_to project_merge_requests_path(@project), class: 'shortcuts-merge_requests' do
Merge Requests %i.fa.fa-tasks
%span.count.merge_counter= @project.merge_requests.opened.count %span
Merge Requests
%span.count.merge_counter= @project.merge_requests.opened.count
- if project_nav_tab? :wiki - if project_nav_tab? :wiki
= nav_link(controller: :wikis) do = nav_link(controller: :wikis) do
= link_to 'Wiki', project_wiki_path(@project, :home), class: 'shortcuts-wiki' = link_to project_wiki_path(@project, :home), class: 'shortcuts-wiki' do
%i.fa.fa-book
%span
Wiki
- if project_nav_tab? :snippets - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to 'Snippets', project_snippets_path(@project), class: 'shortcuts-snippets' = link_to project_snippets_path(@project), class: 'shortcuts-snippets' do
%i.fa.fa-file-text-o
%span
Snippets
- if project_nav_tab? :settings - if project_nav_tab? :settings
= nav_link(html_options: {class: "#{project_tab_class}"}) do = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
= link_to edit_project_path(@project), class: "stat-tab tab " do = link_to edit_project_path(@project), class: "stat-tab tab no-highlight" do
Settings %i.fa.fa-cogs
%span
Settings
%i.fa.fa-angle-down
- if @project_settings_nav
= render 'projects/settings_nav'
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: @title = render "layouts/head", title: @title
%body{class: "#{app_theme} application", :'data-page' => body_data_page} %body{class: "#{app_theme} #{theme_type} application", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: @title = render "layouts/head_panel", title: @title
.container.navless-container .container.navless-container
......
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: "Profile" = render "layouts/head", title: "Profile"
%body{class: "#{app_theme} profile", :'data-page' => body_data_page} %body{class: "#{app_theme} #{theme_type} profile", :'data-page' => body_data_page}
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: "Profile" = render "layouts/head_panel", title: "Profile"
%nav.main-nav.navbar-collapse.collapse = render 'layouts/page', sidebar: 'layouts/nav/profile'
.container= render 'layouts/nav/profile'
.container
.content
= render "layouts/flash"
= yield
!!! 5 !!! 5
%html{ lang: "en"} %html{ lang: "en"}
= render "layouts/head", title: @project.name_with_namespace = render "layouts/head", title: @project.name_with_namespace
%body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } %body{class: "#{app_theme} #{theme_type} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/head_panel", title: project_title(@project) = render "layouts/head_panel", title: project_title(@project)
= render "layouts/init_auto_complete" = render "layouts/init_auto_complete"
- if can?(current_user, :download_code, @project) - if can?(current_user, :download_code, @project)
= render 'shared/no_ssh' = render 'shared/no_ssh'
%nav.main-nav.navbar-collapse.collapse
.container= render 'layouts/nav/project' - @project_settings_nav = true
.container = render 'layouts/page', sidebar: 'layouts/nav/project'
.content
= render "layouts/flash"
.row
.col-md-2
= render "projects/settings_nav"
.col-md-10
= yield
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment