Commit 74e960e5 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'ce_upstream' into 'master'

CE upstream



See merge request !228
parents 9e12d820 9fcdcb8b
......@@ -25,7 +25,12 @@ before_script:
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
- RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate
stages:
- test
- notifications
spec:feature:
stage: test
script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
......@@ -34,6 +39,7 @@ spec:feature:
- mysql
spec:api:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
tags:
......@@ -41,6 +47,7 @@ spec:api:
- mysql
spec:models:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
tags:
......@@ -48,6 +55,7 @@ spec:models:
- mysql
spec:lib:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
tags:
......@@ -55,6 +63,7 @@ spec:lib:
- mysql
spec:services:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
tags:
......@@ -62,6 +71,7 @@ spec:services:
- mysql
spec:benchmark:
stage: test
script:
- RAILS_ENV=test bundle exec rake spec:benchmark
tags:
......@@ -70,6 +80,7 @@ spec:benchmark:
allow_failure: true
spec:other:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
tags:
......@@ -77,6 +88,7 @@ spec:other:
- mysql
spinach:project:half:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
tags:
......@@ -84,6 +96,7 @@ spinach:project:half:
- mysql
spinach:project:rest:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
tags:
......@@ -91,6 +104,7 @@ spinach:project:rest:
- mysql
spinach:other:
stage: test
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
tags:
......@@ -98,6 +112,7 @@ spinach:other:
- mysql
teaspoon:
stage: test
script:
- RAILS_ENV=test bundle exec teaspoon
tags:
......@@ -105,6 +120,7 @@ teaspoon:
- mysql
rubocop:
stage: test
script:
- bundle exec rubocop
tags:
......@@ -112,6 +128,7 @@ rubocop:
- mysql
brakeman:
stage: test
script:
- bundle exec rake brakeman
tags:
......@@ -119,6 +136,7 @@ brakeman:
- mysql
flog:
stage: test
script:
- bundle exec rake flog
tags:
......@@ -126,6 +144,7 @@ flog:
- mysql
flay:
stage: test
script:
- bundle exec rake flay
tags:
......@@ -133,6 +152,7 @@ flay:
- mysql
bundler:audit:
stage: test
script:
- "bundle exec bundle-audit update"
- "bundle exec bundle-audit check"
......@@ -144,6 +164,7 @@ bundler:audit:
# Ruby 2.2 jobs
spec:feature:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -159,6 +180,7 @@ spec:feature:ruby22:
- mysql
spec:api:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -173,6 +195,7 @@ spec:api:ruby22:
- mysql
spec:models:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -187,6 +210,7 @@ spec:models:ruby22:
- mysql
spec:lib:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -201,6 +225,7 @@ spec:lib:ruby22:
- mysql
spec:services:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -215,6 +240,7 @@ spec:services:ruby22:
- mysql
spec:benchmark:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -230,6 +256,7 @@ spec:benchmark:ruby22:
allow_failure: true
spec:other:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -244,6 +271,7 @@ spec:other:ruby22:
- mysql
spinach:project:half:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -258,6 +286,7 @@ spinach:project:half:ruby22:
- mysql
spinach:project:rest:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -272,6 +301,7 @@ spinach:project:rest:ruby22:
- mysql
spinach:other:ruby22:
stage: test
image: ruby:2.2
only:
- master
......@@ -285,3 +315,14 @@ spinach:other:ruby22:
- ruby
- mysql
notify:slack:
stage: notifications
script:
- ./scripts/notify_slack.sh "#builds" "Build failed for master/tags!"
when: on_failure
only:
- master@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- tags@gitlab-org/gitlab-ee
\ No newline at end of file
Please view this file on the master branch, on stable branches it's out of date.
v 8.6.0 (unreleased)
- Improve the formatting for the user page bio (Connor Shea)
v 8.5.1
- Fix group projects styles
- Show Crowd login tab when sign in is disabled and Crowd is enabled (Peter Hudec)
- Fix a set of small UI glitches in project, profile, and wiki pages
- Restrict permissions on public/uploads
- Fix the merge request side-by-side view after loading diff results
- Fix the look of tooltip for the "Revert" button
- Add when the Builds & Runners API changes got introduced
- Fix error 500 on some merged merge requests
- Fix an issue causing the content of the issuable sidebar to disappear
- Fix error 500 when trying to mark an already done todo as "done"
- Fix an issue where MRs weren't sortable
- Issues can now be dragged & dropped into empty milestone lists. This is also
possible with MRs
- Changed padding & background color for highlighted notes
- Re-add the newrelic_rpm gem which was removed without any deprecation or warning (Stan Hu)
- Update sentry-raven gem to 0.15.6
- Add build coverage in project's builds page (Steffen Köhler)
v 8.5.2
- Fix error 500 when commenting on a commit
v 8.5.1
- Fix group projects styles
......@@ -99,6 +122,9 @@ v 8.5.0
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Add Todos
v 8.4.5
- No CE-specific changes
v 8.4.4
- Update omniauth-saml gem to 1.4.2
- Prevent long-running backup tasks from timing out the database connection
......
......@@ -34,7 +34,7 @@ source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
If you have read this guide and want to know how the GitLab [core-team][]
If you have read this guide and want to know how the GitLab [core team][core-team]
operates please see [the GitLab contributing process](PROCESS.md).
## Contributor license agreement
......@@ -68,10 +68,10 @@ for audiences of all ages.
## Helping others
Please help other GitLab users when you can. The channels people will reach out
on can be found on the [getting help page][].
on can be found on the [getting help page][getting-help].
Sign up for the mailing list, answer GitLab questions on StackOverflow or
respond in the IRC channel. You can also sign up on [CodeTriage][] to help with
respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
the remaining issues on the GitHub issue tracker.
## I want to contribute!
......@@ -115,7 +115,7 @@ For feature proposals for EE, open an issue on the
In order to help track the feature proposals, we have created a
[`feature proposal`][fpl] label. For the time being, users that are not members
of the project cannot add labels. You can instead ask one of the [core team][]
of the project cannot add labels. You can instead ask one of the [core team][core-team]
members to add the label `feature proposal` to the issue.
Please keep feature proposals as small and simple as possible, complex ones
......@@ -299,8 +299,8 @@ to us than having a minimal commit log. The smaller an MR is the more likely it
is it will be merged (quickly). After that you can send more MRs to enhance it.
For examples of feedback on merge requests please look at already
[closed merge requests][]. If you would like quick feedback on your merge
request feel free to mention one of the Merge Marshalls of the [core team][].
[closed merge requests][closed-merge-requests]. If you would like quick feedback on your merge
request feel free to mention one of the Merge Marshalls of the [core team][core-team].
Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the
......@@ -369,7 +369,7 @@ Like all merge requests the target should be master so all bugfixes are in maste
## Definition of done
If you contribute to GitLab please know that changes involve more than just
code. We have the following [definition of done][]. Please ensure you support
code. We have the following [definition of done][definition-of-done]. Please ensure you support
the feature you contribute through all of these steps.
1. Description explaining the relevancy (see following item)
......@@ -448,12 +448,12 @@ when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior can be
reported by emailing `contact@gitlab.com`.
This Code of Conduct is adapted from the [Contributor Covenant][], version 1.1.0,
This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
[core-team]: https://about.gitlab.com/core-team/
[getting help page]: https://about.gitlab.com/getting-help/
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
[medium-up-for-grabs]: https://medium.com/@kentcdodds/first-timers-only-78281ea47455
[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
......@@ -467,9 +467,9 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[github-mr-tracker]: https://github.com/gitlabhq/gitlabhq/pulls
[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
[closed merge requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
[definition of done]: http://guide.agilealliance.org/guide/definition-of-done.html
[Contributor Covenant]: http://contributor-covenant.org
[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
[contributor-covenant]: http://contributor-covenant.org
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
......@@ -228,7 +228,7 @@ gem 'virtus', '~> 1.0.1'
gem 'net-ssh', '~> 3.0.1'
gem "gitlab-license", "~> 0.0.4"
# Sentry integration
gem 'sentry-raven'
gem 'sentry-raven', '~> 0.15'
# Metrics
group :metrics do
......@@ -313,6 +313,8 @@ group :production do
gem "gitlab_meta", '7.0'
end
gem "newrelic_rpm", '~> 3.14'
gem 'octokit', '~> 3.8.0'
gem "mail_room", "~> 0.6.1"
......
......@@ -503,6 +503,7 @@ GEM
net-ldap (0.12.1)
net-ssh (3.0.1)
netrc (0.11.0)
newrelic_rpm (3.14.1.311)
nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2)
nprogress-rails (0.1.6.7)
......@@ -746,7 +747,7 @@ GEM
activesupport (>= 3.1, < 4.3)
select2-rails (3.5.9.3)
thor (~> 0.14)
sentry-raven (0.15.4)
sentry-raven (0.15.6)
faraday (>= 0.7.6)
settingslogic (2.0.9)
sexp_processor (4.6.0)
......@@ -992,6 +993,7 @@ DEPENDENCIES
nested_form (~> 0.3.2)
net-ldap
net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.14)
nokogiri (~> 1.6.7, >= 1.6.7.2)
nprogress-rails (~> 0.1.6.7)
oauth2 (~> 1.0.0)
......@@ -1040,7 +1042,7 @@ DEPENDENCIES
sdoc (~> 0.3.20)
seed-fu (~> 2.3.5)
select2-rails (~> 3.5.9)
sentry-raven
sentry-raven (~> 0.15)
settingslogic (~> 2.0.9)
sham_rack
shoulda-matchers (~> 2.8.0)
......
class @Activities
constructor: ->
Pager.init 20, true
$(".event-filter a").bind "click", (event) =>
$(".event-filter-link").on "click", (event) =>
event.preventDefault()
@toggleFilter($(event.currentTarget))
@reloadActivities()
......@@ -12,18 +12,10 @@ class @Activities
toggleFilter: (sender) ->
sender.closest('li').toggleClass "active"
$('.event-filter .active').removeClass "active"
event_filters = $.cookie("event_filter")
filter = sender.attr("id").split("_")[0]
if event_filters
event_filters = event_filters.split(",")
else
event_filters = new Array()
$.cookie "event_filter", (if event_filters isnt filter then filter else ""), { path: '/' }
index = event_filters.indexOf(filter)
if index is -1
event_filters.push filter
else
event_filters.splice index, 1
$.cookie "event_filter", event_filters.join(","), { path: '/' }
if event_filters isnt filter
sender.closest('li').toggleClass "active"
......@@ -214,7 +214,7 @@ $ ->
$this = $(this)
$this.attr 'value', $this.val()
return
$(document)
.off 'keyup', 'input[type="search"]'
.on 'keyup', 'input[type="search"]' , (e) ->
......@@ -257,7 +257,7 @@ $ ->
$('.page-with-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
$.cookie("collapsed_gutter",
$.cookie("collapsed_gutter",
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
......
class @AwardsHandler
constructor: (@post_emoji_url, @noteable_type, @noteable_id, @aliases) ->
$(".add-award").click (event)->
$(".add-award").click (event) =>
event.stopPropagation()
event.preventDefault()
$(".emoji-menu").show()
$("#emoji_search").focus()
@showEmojiMenu()
$("html").on 'click', (event) ->
if !$(event.target).closest(".emoji-menu").length
......@@ -14,6 +14,16 @@ class @AwardsHandler
@renderFrequentlyUsedBlock()
@setupSearch()
showEmojiMenu: ->
if $(".emoji-menu").length
$(".emoji-menu").show()
$("#emoji_search").focus()
else
$.get "/emojis", (response) ->
$(".add-award").after response
$(".emoji-menu").show()
$("#emoji_search").focus()
addAward: (emoji) ->
emoji = @normilizeEmojiName(emoji)
@postEmoji emoji, =>
......
......@@ -76,6 +76,8 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation()
when 'projects:show'
shortcut_handler = new ShortcutsNavigation()
new TreeView() if $('#tree-slider').length
when 'groups:show'
new Activities()
shortcut_handler = new ShortcutsNavigation()
......@@ -88,6 +90,7 @@ class Dispatcher
when 'groups:new', 'groups:edit', 'admin:groups:edit', 'admin:groups:new'
new GroupAvatar()
when 'projects:tree:show'
shortcut_handler = new ShortcutsNavigation()
new TreeView()
when 'projects:find_file:show'
shortcut_handler = true
......
......@@ -70,6 +70,7 @@ class @MergeRequestTabs
@loadCommits($target.attr('href'))
else if action == 'diffs'
@loadDiff($target.attr('href'))
@shrinkView()
else if action == 'builds'
@loadBuilds($target.attr('href'))
......@@ -185,3 +186,14 @@ class @MergeRequestTabs
expandViewContainer: ->
$('.container-fluid').removeClass('container-limited')
shrinkView: ->
$gutterIcon = $('.gutter-toggle i')
# Wait until listeners are set
setTimeout( ->
# Only when sidebar is collapsed
if $gutterIcon.is('.fa-angle-double-right')
$gutterIcon.closest('a').trigger('click')
, 0)
......@@ -62,6 +62,11 @@ class @Milestone
dataType: "json"
constructor: ->
oldMouseStart = $.ui.sortable.prototype._mouseStart
$.ui.sortable.prototype._mouseStart = (event, overrideHandle, noActivation) ->
this._trigger "beforeStart", event, this._uiHash()
oldMouseStart.apply this, [event, overrideHandle, noActivation]
@bindIssuesSorting()
@bindMergeRequestSorting()
@bindTabsSwitching
......@@ -71,6 +76,10 @@ class @Milestone
connectWith: ".issues-sortable-list",
dropOnEmpty: true,
items: "li:not(.ui-sort-disabled)",
beforeStart: (event, ui) ->
$(".issues-sortable-list").css "min-height", ui.item.outerHeight()
stop: (event, ui) ->
$(".issues-sortable-list").css "min-height", "0px"
update: (event, ui) ->
data = $(this).sortable("serialize")
Milestone.sortIssues(data)
......@@ -96,10 +105,22 @@ class @Milestone
).disableSelection()
bindMergeRequestSorting: ->
$('a[data-toggle="tab"]').on 'show.bs.tab', (e) ->
currentTabClass = $(e.target).data('show')
previousTabClass = $(e.relatedTarget).data('show')
$(previousTabClass).hide()
$(currentTabClass).removeClass('hidden')
$(currentTabClass).show()
$("#merge_requests-list-unassigned, #merge_requests-list-ongoing, #merge_requests-list-closed").sortable(
connectWith: ".merge_requests-sortable-list",
dropOnEmpty: true,
items: "li:not(.ui-sort-disabled)",
beforeStart: (event, ui) ->
$(".merge_requests-sortable-list").css "min-height", ui.item.outerHeight()
stop: (event, ui) ->
$(".merge_requests-sortable-list").css "min-height", "0px"
update: (event, ui) ->
data = $(this).sortable("serialize")
Milestone.sortMergeRequests(data)
......@@ -123,12 +144,3 @@ class @Milestone
Milestone.updateMergeRequest(ui.item, merge_request_url, data)
).disableSelection()
bindMergeRequestSorting: ->
$('a[data-toggle="tab"]').on 'show.bs.tab', (e) ->
currentTabClass = $(e.target).data('show')
previousTabClass = $(e.relatedTarget).data('show')
$(previousTabClass).hide()
$(currentTabClass).removeClass('hidden')
$(currentTabClass).show()
......@@ -24,6 +24,10 @@ class @ShortcutsIssuable extends ShortcutsNavigation
@nextIssue()
return false
)
Mousetrap.bind('e', =>
@editIssue()
return false
)
if isMergeRequest
......@@ -63,3 +67,7 @@ class @ShortcutsIssuable extends ShortcutsNavigation
# Focus the input field
replyField.focus()
editIssue: ->
$editBtn = $('.issuable-edit')
Turbolinks.visit($editBtn.attr('href'))
......@@ -8,4 +8,10 @@ $(document).on("click", '.toggle-nav-collapse', (e) ->
$('.sidebar-wrapper').toggleClass("sidebar-collapsed sidebar-expanded")
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
setTimeout ( ->
niceScrollBars = $('.nicescroll').niceScroll();
niceScrollBars.updateScrollBar();
), 300
)
......@@ -2,7 +2,7 @@
class @Wikis
constructor: ->
$('.build-new-wiki').bind 'click', (e) =>
$('.new-wiki-page').on 'submit', (e) =>
$('[data-error~=slug]').addClass('hidden')
field = $('#new_wiki_path')
slug = @slugify(field.val())
......@@ -10,6 +10,7 @@ class @Wikis
if (slug.length > 0)
path = field.attr('data-wikis-path')
location.href = path + '/' + slug
e.preventDefault()
dasherize: (value) ->
value.replace(/[_\s]+/g, '-')
......
......@@ -66,7 +66,7 @@
}
.oneline {
line-height: 42px;
line-height: 35px;
}
> p:last-child {
......
......@@ -7,7 +7,7 @@
&:focus,
&:active {
outline: none;
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
@include box-shadow($gl-btn-active-background);
}
}
......@@ -28,7 +28,7 @@
}
&:active {
@include box-shadow (inset 0 0 4px rgba(0, 0, 0, 0.12));
@include box-shadow ($gl-btn-active-background);
background-color: $dark;
border-color: $border-dark;
......@@ -68,6 +68,12 @@
@include btn-default;
@include btn-white;
color: $gl-text-color;
&:focus:active {
outline: 0;
}
&.btn-small,
&.btn-sm {
padding: 4px 10px;
......@@ -130,6 +136,11 @@
&.disabled {
pointer-events: auto !important;
}
.caret {
margin-left: 5px;
color: $gray-darkest;
}
}
.btn-block {
......@@ -179,7 +190,7 @@
}
.active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
@include box-shadow($gl-btn-active-background);
border: 1px solid #c6cacf !important;
background-color: #e4e7ed !important;
......
......@@ -56,6 +56,10 @@ hr {
margin: $gl-padding 0;
}
.dropdown-menu {
margin: 6px 0 0;
}
.dropdown-menu > li > a {
text-shadow: none;
}
......@@ -386,6 +390,7 @@ table {
}
.project-item-select-holder {
display: inline-block;
position: relative;
.project-item-select {
......
......@@ -158,7 +158,7 @@
}
&:hover {
background: $hover;
background: $row-hover;
}
}
}
......
......@@ -21,10 +21,3 @@
}
}
}
.issues-filters,
.issues_bulk_update {
.select2-container .select2-choice {
color: #444 !important;
}
}
......@@ -142,9 +142,13 @@ header {
}
@media (max-width: $screen-md-max) {
.header-collapsed, .header-expanded {
@include collapsed-header;
.header-collapsed {
margin-left: $sidebar_collapsed_width;
}
.header-expanded {
margin-left: $sidebar_width;
}
}
@media(min-width: $screen-md-max) {
......
......@@ -48,8 +48,8 @@
.ui-state-hover,
.ui-state-focus {
border: 1px solid $hover;
background: $hover;
border: 1px solid $row-hover;
background: $row-hover;
color: #333;
}
}
......
......@@ -38,7 +38,7 @@
&.smoke { background-color: $background-color; }
&:hover {
background: $hover;
background: $row-hover;
}
&:last-child {
......
......@@ -77,12 +77,21 @@
margin-bottom: 0px;
> .dropdown {
margin-right: 10px;
margin-right: $gl-padding-top;
display: inline-block;
}
> .btn {
margin-right: $gl-padding-top;
display: inline-block;
&:last-child {
margin-right: 0;
}
}
> .btn-grouped {
float: none;
}
> form {
......@@ -94,7 +103,7 @@
display: inline-block;
position: relative;
top: 1px;
margin-right: 10px;
margin-right: $gl-padding-top;
/* Medium devices (desktops, 992px and up) */
@media (min-width: $screen-md-min) { width: 200px; }
......
/** Select2 selectbox style override **/
.select2-container {
width: 100% !important;
}
.select2-container, .select2-container.select2-drop-above {
.select2-choice {
background: #FFF;
border-color: #DDD;
height: 36px;
padding: 6px $gl-padding;
background: #fff;
border-color: $input-border;
border-color: $border-white-light;
height: 35px;
padding: $gl-vert-padding $gl-btn-padding;
font-size: $gl-font-size;
line-height: 1.42857143;
@include border-radius(2px);
@include border-radius($border-radius-default);
.select2-arrow {
background: #FFF;
border-left: none;
padding-top: 5px;
background-image: none;
background-color: transparent;
border: none;
padding-top: 6px;
padding-right: 10px;
b {
@extend .caret;
color: $gray-darkest;
}
}
.select2-chosen {
color: $gl-text-color;
margin-right: 15px;
}
&.select2-default {
.select2-chosen {
color: #999;
}
&:hover {
background-color: $gray-dark;
border-color: $border-white-normal;
color: $gl-text-color;
}
}
}
.select2-container .select2-choice, .select2-container.select2-drop-above .select2-choice{
color: #7f8fa4;
border: 1px solid #e7e9ed;
}
.select2-drop {
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
@include border-radius (0px);
padding: 16px;
border: none !important;
@include border-radius ($border-radius-default);
border: none;
}
.select2-results .select2-result-label {
padding: 9px;
padding: 10px 15px;
}
.select2-drop{
......@@ -56,15 +60,30 @@
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: 600;
color: #313236;
color: $gl-text-color;
}
.select2-container-active {
.select2-choice, .select2-choices {
@include box-shadow(none);
}
}
.select2-dropdown-open {
.select2-choice {
border-color: $border-white-normal;
outline: 0;
background-image: none;
background-color: $white-dark;
@include box-shadow($gl-btn-active-gradient);
}
}
.select2-container-multi {
.select2-choices {
@include border-radius(2px);
@include border-radius($border-radius-default);
border-color: $input-border;
background: white;
padding-left: $gl-padding / 2;
background: none;
.select2-search-field input {
padding: $gl-padding / 2;
......@@ -76,14 +95,16 @@
.select2-search-choice {
margin: 8px 0 0 8px;
background: white;
box-shadow: none;
border-color: $input-border;
color: $gl-text-color;
line-height: 15px;
background-color: $background-color;
background-image: none;
.select2-search-choice-close {
top: 5px;
top: 4px;
left: 3px;
}
&.select2-search-choice-focus {
......@@ -91,22 +112,25 @@
}
}
}
&.select2-container-active .select2-choices,
&.select2-dropdown-open .select2-choices {
border-color: $border-white-normal;
@include box-shadow($gl-btn-active-gradient);
}
}
.select2-container-multi .select2-choices .select2-search-choice {
}
.select2-drop-active {
border: 1px solid #BBB !important;
margin-top: 4px;
font-size: 13px;
margin-top: 6px;
font-size: 14px;
&.select2-drop-above {
margin-bottom: 8px;
}
.select2-search input {
background: #fafafa;
border-color: #DDD;
}
.select2-results {
max-height: 350px;
.select2-highlighted {
......@@ -115,8 +139,34 @@
}
}
.select2-container {
width: 100% !important;
.select2-search {
padding: 15px 15px 5px;
.select2-drop-auto-width & {
padding: 15px 15px 5px;
}
}
.select2-search input {
padding: 2px 25px 2px 5px;
background: #fff image-url('select2.png');
background-repeat: no-repeat;
background-position: right 0px bottom 6px;
border: 1px solid $input-border;
@include border-radius($border-radius-default);
@include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s);
&:focus {
border-color: $input-border-focus;
}
}
.select2-search input.select2-active {
background-color: #fff;
background-image: image-url('select2-spinner.gif') !important;
background-repeat: no-repeat;
background-position: right 5px center !important;
background-size: 16px 16px !important;
}
/** Branch/tag selector **/
......@@ -124,10 +174,19 @@
width: 160px !important;
}
.ajax-users-dropdown, .ajax-project-users-dropdown {
.select2-search {
padding-top: 2px;
}
.select2-results .select2-no-results,
.select2-results .select2-searching,
.select2-results .select2-ajax-error,
.select2-results .select2-selection-limit {
background: $gray-light;
display: list-item;
padding: 10px 15px;
}
.select2-results {
margin: 0;
padding: 10px 0;
}
.ajax-users-select {
......
......@@ -12,6 +12,10 @@
height: 100%;
transition-duration: .3s;
}
&.right-sidebar-expanded {
padding-right: $gutter_width;
}
}
.sidebar-wrapper {
......@@ -45,19 +49,6 @@
overflow: hidden;
transition-duration: .3s;
.home {
z-index: 1;
position: absolute;
left: 0px;
}
#logo {
z-index: 2;
position: absolute;
width: 58px;
cursor: pointer;
}
a {
float: left;
height: $header-height;
......@@ -83,7 +74,7 @@
width: 158px;
float: left;
margin: 0;
margin-left: 50px;
margin-left: 14px;
font-size: 19px;
line-height: 41px;
font-weight: normal;
......@@ -194,6 +185,10 @@
@mixin expanded-sidebar {
padding-left: $sidebar_width;
&.right-sidebar-collapsed {
padding-right: $sidebar_collapsed_width;
}
.sidebar-wrapper {
width: $sidebar_width;
......@@ -213,17 +208,13 @@
}
}
@mixin expanded-gutter {
padding-right: $gutter_width;
}
@mixin collapsed-gutter {
padding-right: $sidebar_collapsed_width;
}
@mixin collapsed-sidebar {
padding-left: $sidebar_collapsed_width;
&.right-sidebar-collapsed {
padding-right: $sidebar_collapsed_width;
}
.sidebar-wrapper {
width: $sidebar_collapsed_width;
......@@ -287,47 +278,10 @@
background: #f2f6f7;
}
// page is small enough
@media (max-width: $screen-md-max) {
.page-sidebar-collapsed {
@include collapsed-sidebar;
}
.page-sidebar-expanded {
@include collapsed-sidebar;
}
.page-gutter {
&.right-sidebar-collapsed {
@include collapsed-gutter;
}
&.right-sidebar-expanded {
@include expanded-gutter;
}
}
.collapse-nav {
display: none;
}
.page-sidebar-collapsed {
@include collapsed-sidebar;
}
// page is large enough
@media(min-width: $screen-md-max) {
.page-gutter {
&.right-sidebar-collapsed {
@include collapsed-gutter;
}
&.right-sidebar-expanded {
@include expanded-gutter;
}
}
.page-sidebar-collapsed {
@include collapsed-sidebar;
}
.page-sidebar-expanded {
@include expanded-sidebar;
}
}
\ No newline at end of file
.page-sidebar-expanded {
@include expanded-sidebar;
}
......@@ -5,13 +5,13 @@
padding: 0;
.timeline-entry {
padding: $gl-padding 0;
padding: $gl-padding $gl-btn-padding;
border-color: $table-border-color;
color: $gl-gray;
border-bottom: 1px solid $border-white-light;
&:target {
background: $hover;
background: $row-hover;
}
&:last-child {
......
......@@ -70,7 +70,7 @@ $pagination-bg: #fff;
$pagination-border: $border-color;
$pagination-hover-color: $gl-gray;
$pagination-hover-bg: $hover;
$pagination-hover-bg: $row-hover;
$pagination-hover-border: $border-color;
$pagination-active-color: $blue-dark;
......
$hover: #faf9f9;
$row-hover: #f4f8fe;
$gl-text-color: #54565B;
$gl-text-green: #4A2;
$gl-text-red: #D12F19;
......@@ -31,6 +31,7 @@ $gl-padding-top:10px;
$gl-avatar-size: 40px;
$secondary-text: #7f8fa4;
$error-exclamation-point: #E62958;
$border-radius-default: 3px;
/*
* Color schema
......@@ -100,6 +101,8 @@ $gl-success: $green-normal;
$gl-info: $blue-normal;
$gl-warning: $orange-normal;
$gl-danger: $red-normal;
$gl-btn-active-background: rgba(0, 0, 0, 0.12);
$gl-btn-active-gradient: inset 0 0 4px $gl-btn-active-background;
/*
* Commit Diff Colors
......
......@@ -51,9 +51,17 @@
.profile-link-holder {
display: inline;
a {
color: $blue-dark;
text-decoration: none;
}
}
// Middle dot divider between each element in a list of items.
.middle-dot-divider {
&:after {
content: "\00B7";
padding: 0px 6px;
content: "\00B7"; // Middle Dot
padding: 0 6px;
font-weight: bold;
}
......@@ -63,9 +71,10 @@
padding: 0;
}
}
}
a {
color: $blue-dark;
text-decoration: none;
}
.profile-user-bio {
// Limits the width of the user bio for readability.
max-width: 750px;
margin: auto;
}
......@@ -32,6 +32,7 @@
.cover-controls {
.project-settings-dropdown {
margin-left: 10px;
display: inline-block;
}
}
......@@ -186,10 +187,10 @@
.dropdown-menu {
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
@include border-radius (0px);
@include border-radius ($border-radius-default);
border: none;
padding: 16px 0;
padding: 10px 0;
font-size: 14px;
font-weight: 100;
......
......@@ -21,7 +21,7 @@
&:hover {
td {
background: $hover;
background: $row-hover;
}
cursor: pointer;
}
......
......@@ -4,8 +4,3 @@
margin-right: auto;
padding-right: 7px;
}
.wiki-last-edit-by {
font-size: 80%;
font-weight: normal;
}
......@@ -15,7 +15,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
end
def destroy_all
@todos.each(&:done)
@todos.each(&:done!)
respond_to do |format|
format.html { redirect_to dashboard_todos_path, notice: 'All todos were marked as done.' }
......
class EmojisController < ApplicationController
layout false
def index
end
end
......@@ -64,9 +64,9 @@ class Projects::RefsController < Projects::ApplicationController
}
end
if @logs.present?
@log_url = namespace_project_tree_url(@project.namespace, @project, tree_join(@ref, @path || '/'))
@more_log_url = logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: (@offset + @limit))
offset = (@offset + @limit)
if contents.size > offset
@more_log_url = logs_file_namespace_project_ref_path(@project.namespace, @project, @ref, @path || '', offset: offset)
end
respond_to do |format|
......
......@@ -10,6 +10,10 @@ module AuthHelper
auth_providers.include?(:kerberos)
end
def omniauth_enabled?
Gitlab.config.omniauth.enabled
end
def provider_has_icon?(name)
PROVIDERS_WITH_ICONS.include?(name.to_s)
end
......
......@@ -36,7 +36,7 @@ class Todo < ActiveRecord::Base
state_machine :state, initial: :pending do
event :done do
transition pending: :done
transition [:pending, :done] => :done
end
state :pending
......
......@@ -13,6 +13,5 @@ module Notes
note
end
end
end
......@@ -130,8 +130,8 @@ class TodoService
end
def handle_note(note, author)
# Skip system notes, like status changes and cross-references
return if note.system
# Skip system notes, notes on commit, and notes on project snippet
return if note.system? || ['Commit', 'Snippet'].include?(note.noteable_type)
project = note.project
target = note.noteable
......
- page_title "Sign in"
%div
- if signin_enabled? || ldap_enabled?
- if signin_enabled? || ldap_enabled? || crowd_enabled?
= render 'devise/shared/signin_box'
-# Omniauth fits between signin/ldap signin and signup and does not have a surrounding box
- if Gitlab.config.omniauth.enabled && devise_mapping.omniauthable? && button_based_providers.any?
- if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers.any?
.clearfix.prepend-top-20
= render 'devise/shared/omniauth_box'
......@@ -14,6 +14,6 @@
= render 'devise/shared/signup_box'
-# Show a message if none of the mechanisms above are enabled
- if !signin_enabled? && !ldap_enabled? && !(Gitlab.config.omniauth.enabled && devise_mapping.omniauthable?)
- if !signin_enabled? && !ldap_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?)
%div
No authentication methods configured.
.emoji-menu
.emoji-menu-content
= text_field_tag :emoji_search, "", class: "emoji-search search-input form-control"
- AwardEmoji.emoji_by_category.each do |category, emojis|
%h5= AwardEmoji::CATEGORIES[category]
%ul
- emojis.each do |emoji|
%li
= emoji_icon(emoji["name"], emoji["unicode"], emoji["aliases"])
\ No newline at end of file
.top-area
.nav-controls
= form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
= search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'input-short project-filter-form-field form-control projects-list-filter', spellcheck: false, id: 'project-filter-form-field'
- if current_user && current_user.can_create_project?
= link_to new_project_path, class: 'btn btn-new' do
= icon('plus')
New Project
- if @projects.present?
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
- if can? current_user, :create_projects, @group
= link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new pull-right' do
= icon('plus')
New Project
.projects-list-holder
= render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true
......@@ -32,10 +32,9 @@
%li.active
= link_to "#activity", 'data-toggle' => 'tab' do
Activity
- if @projects.present?
%li
= link_to "#projects", 'data-toggle' => 'tab' do
Projects
%li
= link_to "#projects", 'data-toggle' => 'tab' do
Projects
- if @shared_projects.present?
%li
= link_to "#shared", 'data-toggle' => 'tab' do
......
......@@ -229,6 +229,10 @@
%td.shortcut
.key r
%td Reply (quoting selected text)
%tr
%td.shortcut
.key e
%td Edit issue
%tbody{ class: 'hidden-shortcut merge_requests', style: 'display:none' }
%tr
%th
......@@ -245,3 +249,7 @@
%td.shortcut
.key r
%td Reply (quoting selected text)
%tr
%td.shortcut
.key e
%td Edit merge request
- page_title "Applications"
- header_title page_title, applications_profile_path
.gray-content-block.top-block
.alert.alert-help.prepend-top-default
- if user_oauth_applications?
Manage applications that can use GitLab as an OAuth provider,
and applications that you've authorized to use your account.
......
- page_title "Audit Log"
- header_title page_title, audit_log_profile_path
.gray-content-block.top-block
.alert.alert-help.prepend-top-default
History of authentications
.prepend-top-default
......
- page_title "Emails"
- header_title page_title, profile_emails_path
.gray-content-block.top-block
Control emails linked to your account
%ul.prepend-top-default
%li
Your
%b Primary Email
will be used for avatar detection and web based operations, such as edits and merges.
%li
Your
%b Notification Email
will be used for account notifications.
%li
Your
%b Public Email
will be displayed on your public profile.
%li
All email addresses will be used to identify your commits.
.alert.alert-help.prepend-top-default
%ul
%li
Your
%b Primary Email
will be used for avatar detection and web based operations, such as edits and merges.
%li
Your
%b Notification Email
will be used for account notifications.
%li
Your
%b Public Email
will be displayed on your public profile.
%li
All email addresses will be used to identify your commits.
.panel.panel-default
.panel-heading
......
- page_title "SSH Keys"
- header_title page_title, profile_keys_path
.gray-content-block.top-block
.pull-right
.top-area
.nav-text
Before you can add an SSH key you need to
= link_to "generate it.", help_page_path("ssh", "README")
.nav-controls
= link_to new_profile_key_path, class: "btn btn-new" do
= icon('plus')
Add SSH Key
.oneline
Before you can add an SSH key you need to
= link_to "generate it.", help_page_path("ssh", "README")
.prepend-top-default
= render 'key_table'
- page_title "Notifications"
- header_title page_title, profile_notifications_path
.gray-content-block.top-block
These are your global notification settings.
.prepend-top-default
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications form-horizontal global-notifications-form' } do |f|
-if @user.errors.any?
......
- page_title "Password"
- header_title page_title, edit_profile_password_path
.gray-content-block.top-block
.alert.alert-help.prepend-top-default
- if @user.password_automatically_set?
Set your password.
- else
......
- page_title 'Preferences'
- header_title page_title, profile_preferences_path
- @blank_container = true
.alert.alert-help
.alert.alert-help.prepend-top-default
These settings allow you to customize the appearance and behavior of the site.
They are saved with your account and will persist to any device you use to
access the site.
......
.gray-content-block.top-block
.alert.alert-help.prepend-top-default
This information will appear on your profile.
- if current_user.ldap_user?
Some options are unavailable for LDAP accounts
......
......@@ -51,9 +51,11 @@
%th Name
%th Duration
%th Finished at
- if @project.build_coverage_enabled?
%th Coverage
%th
- @builds.each do |build|
= render 'projects/commit_statuses/commit_status', commit_status: build, commit_sha: true, stage: true, allow_retry: true
= render 'projects/commit_statuses/commit_status', commit_status: build, commit_sha: true, stage: true, coverage: @project.build_coverage_enabled?, allow_retry: true
= paginate @builds, theme: 'gitlab'
- @blank_container = true
.project-edit-container.prepend-top-default
.project-edit-errors
.project-edit-content
......
......@@ -18,7 +18,7 @@
= link_to "adding README", new_readme_path, class: 'underlined-link'
file to this project.
- if can?(current_user, :download_code, @project)
- if can?(current_user, :push_code, @project)
%div{ class: container_class }
.prepend-top-20
.empty_wrapper
......
- content_for :note_actions do
- if can?(current_user, :update_issue, @issue)
= link_to 'Reopen Issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen Issue'
= link_to 'Close Issue', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close Issue'
= link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
#notes
= render 'projects/notes/notes_with_form'
......@@ -8,12 +8,12 @@
.detail-page-header
.pull-right
- if can?(current_user, :create_issue, @project)
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New Issue', id: 'new_issue_link' do
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'btn btn-nr btn-grouped new-issue-link btn-success', title: 'New issue', id: 'new_issue_link' do
= icon('plus')
New Issue
New issue
- if can?(current_user, :update_issue, @issue)
= link_to 'Reopen', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen Issue'
= link_to 'Close', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close Issue'
= link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, status_only: true, format: 'json'), data: {no_turbolink: true}, class: "btn btn-nr btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
= link_to edit_namespace_project_issue_path(@project.namespace, @project, @issue), class: 'btn btn-nr btn-grouped issuable-edit' do
= icon('pencil-square-o')
......
......@@ -8,12 +8,9 @@
row.find("td.tree_time_ago").html('#{escape_javascript time_ago_with_tooltip(commit.committed_date)}');
row.find("td.tree_commit").html('#{escape_javascript render("projects/tree/tree_commit_column", commit: commit)}');
- if @logs.present?
- if @more_log_url
:plain
var current_url = location.href.replace(/\/?$/, '/');
var log_url = "#{escape_javascript(@log_url)}".replace(/\/?$/, '/');
if(current_url == log_url) {
if($('#tree-slider').length) {
// Load more commit logs for each file in tree
// if we still on the same page
var url = "#{escape_javascript(@more_log_url)}";
......
%span.pull-right
- if (@page && @page.persisted?)
= link_to namespace_project_wiki_history_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
Page History
- if can?(current_user, :create_wiki, @project)
= link_to namespace_project_wiki_edit_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
- if can?(current_user, :admin_wiki, @project)
= link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-remove" do
= icon('trash')
Delete
- if (@page && @page.persisted?)
= link_to namespace_project_wiki_history_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
Page History
- if can?(current_user, :create_wiki, @project)
= link_to namespace_project_wiki_edit_path(@project.namespace, @project, @page), class: "btn btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
- if can?(current_user, :admin_wiki, @project)
= link_to namespace_project_wiki_path(@project.namespace, @project, @page), data: { confirm: "Are you sure you want to delete this page?"}, method: :delete, class: "btn btn-remove" do
= icon('trash')
Delete
......@@ -16,4 +16,4 @@
= icon('plus')
New Page
= render 'projects/wikis/new'
= render 'projects/wikis/new'
......@@ -5,9 +5,10 @@
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3.page-title New Wiki Page
.modal-body
.form-group
= label_tag :new_wiki_path do
%span Page slug
= text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => namespace_project_wikis_path(@project.namespace, @project)
.form-actions
= link_to 'Create Page', '#', class: 'build-new-wiki btn btn-create'
%form.new-wiki-page
.form-group
= label_tag :new_wiki_path do
%span Page slug
= text_field_tag :new_wiki_path, nil, placeholder: 'how-to-setup', class: 'form-control', required: true, :'data-wikis-path' => namespace_project_wikis_path(@project.namespace, @project), autofocus: true
.form-actions
= button_tag 'Create Page', class: 'build-new-wiki btn btn-create'
- page_title "Edit", @page.title.capitalize, "Wiki"
= render "header_title"
= render 'nav'
.gray-content-block
.pull-right
.top-area
.nav-text
%strong
- if @page.persisted?
= link_to @page.title.capitalize, namespace_project_wiki_path(@project.namespace, @project, @page)
- else
= @page.title.capitalize
%span.light
&middot;
Edit Page
.nav-controls
= render 'main_links'
%h3.page-title.oneline
%span.light Edit Page
- if @page.persisted?
= link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
- else
= @page.title
= render 'form'
- page_title "History", @page.title.capitalize, "Wiki"
= render "header_title"
= render 'nav'
.gray-content-block
%h3.page-title
%span.light History for
= link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
.top-area
.nav-text
%strong
= link_to @page.title.capitalize, namespace_project_wiki_path(@project.namespace, @project, @page)
%span.light
&middot;
History
.table-holder
%table.table
......
......@@ -2,15 +2,12 @@
= render "header_title"
= render 'nav'
.gray-content-block
All pages in this wiki are listed below.
%ul.content-list
- @wiki_pages.each do |wiki_page|
%li
%h4
= link_to wiki_page.title, namespace_project_wiki_path(@project.namespace, @project, wiki_page)
%small (#{wiki_page.format})
.pull-right
%small Last edited #{time_ago_with_tooltip(wiki_page.commit.authored_date)}
= link_to wiki_page.title, namespace_project_wiki_path(@project.namespace, @project, wiki_page)
%small (#{wiki_page.format})
.pull-right
%small Last edited #{time_ago_with_tooltip(wiki_page.commit.authored_date)}
= paginate @wiki_pages, theme: 'gitlab'
- page_title @page.title.capitalize, "Wiki"
= render "header_title"
= render 'nav'
.gray-content-block
= render 'main_links'
%h3.page-title.oneline
= @page.title.capitalize
.top-area
.nav-text
%strong= @page.title.capitalize
%span.wiki-last-edit-by
&middot;
last edited by #{@page.commit.author.name} #{time_ago_with_tooltip(@page.commit.authored_date)}
.nav-controls
= render 'main_links'
- if @page.historical?
.warning_message
This is an old version of this page.
......
......@@ -35,35 +35,37 @@
= @user.name
.cover-desc
%span
@#{@user.username}.
- if @user.bio.present?
%span
#{@user.bio}.
%span
%span.middle-dot-divider
@#{@user.username}
%span.middle-dot-divider
Member since #{@user.created_at.to_s(:medium)}
- if @user.bio.present?
.cover-desc
%p.profile-user-bio
= @user.bio
.cover-desc
- unless @user.public_email.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= link_to @user.public_email, "mailto:#{@user.public_email}"
- unless @user.skype.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= link_to "skype:#{@user.skype}", title: "Skype" do
= icon('skype')
- unless @user.linkedin.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= link_to "https://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do
= icon('linkedin-square')
- unless @user.twitter.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= link_to "https://twitter.com/#{@user.twitter}", title: "Twitter" do
= icon('twitter-square')
- unless @user.website_url.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= link_to @user.short_website_url, @user.full_website_url
- unless @user.location.blank?
.profile-link-holder
.profile-link-holder.middle-dot-divider
= icon('map-marker')
= @user.location
......
......@@ -9,15 +9,6 @@
.awards-controls
%a.add-award{"href" => "#"}
= icon('smile-o')
.emoji-menu
.emoji-menu-content
= text_field_tag :emoji_search, "", class: "emoji-search search-input form-control"
- AwardEmoji.emoji_by_category.each do |category, emojis|
%h5= AwardEmoji::CATEGORIES[category]
%ul
- emojis.each do |emoji|
%li
= emoji_icon(emoji["name"], emoji["unicode"], emoji["aliases"])
- if current_user
:javascript
......
# New Relic configuration file
#
# This file is here to make sure the New Relic gem stays
# quiet by default.
#
# To enable and configure New Relic, please use
# environment variables, e.g. NEW_RELIC_ENABLED=true
production:
enabled: false
development:
enabled: false
test:
enabled: false
......@@ -43,6 +43,8 @@ Rails.application.routes.draw do
get '/autocomplete/users' => 'autocomplete#users'
get '/autocomplete/users/:id' => 'autocomplete#user'
# Emojis
resources :emojis, only: :index
# Search
get 'search' => 'search#show'
......
......@@ -42,7 +42,7 @@ Gitlab-shell communicates with Sidekiq via the “communication board” (Redis)
## System Layout
When referring to ~git in the pictures it means the home directory of the git user which is typically /home/git.
When referring to `~git` in the pictures it means the home directory of the git user which is typically /home/git.
GitLab is primarily installed within the `/home/git` user home directory as `git` user. Within the home directory is where the gitlabhq server software resides as well as the repositories (though the repository location is configurable).
......
......@@ -265,8 +265,9 @@ sudo usermod -aG redis git
# Create the public/uploads/ directory
sudo -u git -H mkdir public/uploads/
# Make sure GitLab can write to the public/uploads/ directory
sudo chmod -R u+rwX public/uploads
# Make sure only the GitLab user has access to the public/uploads/ directory
# now that files in public/uploads are served by gitlab-workhorse
sudo chmod 0700 public/uploads
# Change the permissions of the directory where CI build traces are stored
sudo chmod -R u+rwX builds/
......
......@@ -18,7 +18,7 @@ You accept and agree to the following terms and conditions for Your present and
6. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [[]named here]".
7. Should You wish to submit work that is not Your original creation, You may submit it to GitLab B.V. separately from any Contribution, identifying the complete details of its source and of any license or other restriction (including, but not limited to, related patents, trademarks, and license agreements) of which you are personally aware, and conspicuously marking the work as "Submitted on behalf of a third-party: [insert_name_here]".
8. You agree to notify GitLab B.V. of any facts or circumstances of which you become aware that would make these representations inaccurate in any respect.
......
......@@ -26,6 +26,7 @@ documentation](../workflow/add-user/add-user.md).
| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
| Manage merge requests | | | ✓ | ✓ | ✓ |
| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
......@@ -35,6 +36,7 @@ documentation](../workflow/add-user/add-user.md).
| Add tags | | | ✓ | ✓ | ✓ |
| Write a wiki | | | ✓ | ✓ | ✓ |
| Cancel and retry builds | | | ✓ | ✓ | ✓ |
| Create or update commit status | | | ✓ | ✓ | ✓ |
| Create new milestones | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
......
......@@ -69,6 +69,7 @@ branches and tags.
```bash
git remote add origin git@gitlab.com:<group>/<project>.git
git push --all origin
git push --tags origin
```
## Contribute to this guide
......
doc/workflow/shortcuts.png

47.6 KB | W: | H:

doc/workflow/shortcuts.png

24.4 KB | W: | H:

doc/workflow/shortcuts.png
doc/workflow/shortcuts.png
doc/workflow/shortcuts.png
doc/workflow/shortcuts.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -43,10 +43,16 @@ Feature: Event Filters
And I should not see new member event
When I click "team" event filter
And I visit dashboard activity page
Then I should see push event
Then I should not see push event
And I should see new member event
And I should not see merge request event
When I click "push" event filter
Then I should not see push event
And I should see new member event
And I visit dashboard activity page
Then I should see push event
And I should not see new member event
And I should not see merge request event
When I click "merge" event filter
And I visit dashboard activity page
Then I should see merge request event
And I should not see push event
And I should not see new member event
......@@ -87,6 +87,7 @@ Feature: Explore Projects
Scenario: I visit public project issues page as a non authorized user
Given I visit project "Community" page
Then I should not see command line instructions
And I visit "Community" issues page
Then I should see list of issues for "Community" project
......
Feature: Login form
Scenario: I see crowd form
Given Crowd integration enabled
When I visit sign in page
Then I should see Crowd login form
\ No newline at end of file
......@@ -3,6 +3,7 @@ Feature: Project Builds Summary
Given I sign in as a user
And I own a project
And project has CI enabled
And project has coverage enabled
And project has a recent build
Scenario: I browse build details page
......@@ -12,6 +13,7 @@ Feature: Project Builds Summary
Scenario: I browse project builds page
When I visit project builds page
Then I see coverage
Then I see button to CI Lint
Scenario: I erase a build
......
......@@ -105,3 +105,9 @@ Feature: Project
Given I click notifications drop down button
When I choose Mention setting
Then I should see Notification saved message
Scenario: I should see command line instructions
Given I own an empty project
And I visit my empty project page
And I create bare repo
Then I should see command line instructions
......@@ -18,7 +18,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps
end
step 'I should see empty public project details' do
expect(page).to have_content 'Git global setup'
expect(page).not_to have_content 'Git global setup'
end
step 'I should see empty public project details with http clone info' do
......
class Spinach::Features::LoginForm < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedSnippet
include SharedUser
include SharedSearch
step 'Crowd integration enabled' do
@providers_orig = Gitlab::OAuth::Provider.providers
@omniauth_conf_orig = Gitlab.config.omniauth.enabled
expect(Gitlab::OAuth::Provider).to receive(:providers).and_return([:crowd])
allow_any_instance_of(ApplicationHelper).to receive(:user_omniauth_authorize_path).and_return(root_path)
expect(Gitlab.config.omniauth).to receive(:enabled).and_return(true)
end
step 'I should see Crowd login form' do
expect(page).to have_selector '#tab-crowd form'
Gitlab::OAuth::Provider.stub(:providers).and_return(@providers_orig)
Gitlab.config.omniauth.stub(:enabled).and_return(@omniauth_conf_orig)
end
step 'I visit sign in page' do
visit new_user_session_path
end
end
......@@ -97,7 +97,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end
step "I should see a password error message" do
page.within '.alert' do
page.within '.alert-danger' do
expect(page).to have_content "Password confirmation doesn't match"
end
end
......
......@@ -4,6 +4,12 @@ class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps
include SharedBuilds
include RepoHelpers
step 'I see coverage' do
page.within('td.coverage') do
expect(page).to have_content "99.9%"
end
end
step 'I see button to CI Lint' do
page.within('.nav-controls') do
ci_lint_tool_link = page.find_link('CI Lint')
......
......@@ -96,6 +96,7 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
end
step 'The search field is focused' do
page.evaluate_script("document.activeElement.id").should eq "emoji_search"
expect(page).to have_selector('#emoji_search')
expect(page.evaluate_script('document.activeElement.id')).to eq('emoji_search')
end
end
......@@ -194,4 +194,13 @@ class Spinach::Features::Project < Spinach::FeatureSteps
expect(find('.issues-feature')).to be_visible
end
step 'I create bare repo' do
click_link 'Create empty bare repository'
end
step 'I should see command line instructions' do
page.within ".empty_wrapper" do
expect(page).to have_content("Command line instructions")
end
end
end
......@@ -238,7 +238,11 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
step 'I see new wiki page named test' do
expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "test")
expect(page).to have_content "Edit Page test"
page.within(:css, ".nav-text") do
expect(page).to have_content "Test"
expect(page).to have_content "Edit Page"
end
end
When 'I go back to wiki page home' do
......@@ -252,7 +256,11 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
step 'I see Gitlab API document' do
expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "api")
expect(page).to have_content "Edit Page api"
page.within(:css, ".nav-text") do
expect(page).to have_content "Edit"
expect(page).to have_content "Api"
end
end
step 'I click on Rake tasks link' do
......@@ -261,7 +269,11 @@ class Spinach::Features::ProjectSourceMarkdownRender < Spinach::FeatureSteps
step 'I see Rake tasks directory' do
expect(current_path).to eq namespace_project_wiki_path(@project.namespace, @project, "raketasks")
expect(page).to have_content "Edit Page raketasks"
page.within(:css, ".nav-text") do
expect(page).to have_content "Edit"
expect(page).to have_content "Rake"
end
end
step 'I go directory which contains README file' do
......
......@@ -120,7 +120,7 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
step 'I should see the new wiki page form' do
expect(current_path).to match('wikis/image.jpg')
expect(page).to have_content('New Wiki Page')
expect(page).to have_content('Edit Page image.jpg')
expect(page).to have_content('Edit Page')
end
step 'I create a New page with paths' do
......@@ -159,7 +159,9 @@ class Spinach::Features::ProjectWiki < Spinach::FeatureSteps
end
step 'I should see the page history' do
expect(page).to have_content('History for')
page.within(:css, ".nav-text") do
expect(page).to have_content('History')
end
end
step 'I search for Wiki content' do
......
......@@ -5,9 +5,13 @@ module SharedBuilds
@project.enable_ci
end
step 'project has coverage enabled' do
@project.update_attribute(:build_coverage_regex, /Coverage (\d+)%/)
end
step 'project has a recent build' do
@ci_commit = create(:ci_commit, project: @project, sha: @project.commit.sha)
@build = create(:ci_build, commit: @ci_commit)
@build = create(:ci_build_with_coverage, commit: @ci_commit)
end
step 'recent build is successful' do
......
......@@ -483,6 +483,10 @@ module SharedPaths
visit namespace_project_path(project.namespace, project)
end
step "I should not see command line instructions" do
expect(page).not_to have_css('.empty_wrapper')
end
# ----------------------------------------
# Public Projects
# ----------------------------------------
......
......@@ -6,7 +6,7 @@ timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 90 : 15
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout)
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768])
end
Capybara.default_wait_time = timeout
......
......@@ -267,7 +267,7 @@ namespace :gitlab do
unless File.directory?(Rails.root.join('public/uploads'))
puts "no".red
try_fixing_it(
"sudo -u #{gitlab_user} mkdir -m 750 #{Rails.root}/public/uploads"
"sudo -u #{gitlab_user} mkdir #{Rails.root}/public/uploads"
)
for_more_information(
see_installation_guide_section "GitLab"
......@@ -279,21 +279,22 @@ namespace :gitlab do
upload_path = File.realpath(Rails.root.join('public/uploads'))
upload_path_tmp = File.join(upload_path, 'tmp')
if File.stat(upload_path).mode == 040750
if File.stat(upload_path).mode == 040700
unless Dir.exists?(upload_path_tmp)
puts 'skipped (no tmp uploads folder yet)'.magenta
return
end
# if tmp upload dir has incorrect permissions, assume others do as well
if File.stat(upload_path_tmp).mode == 040755 && File.owned?(upload_path_tmp) # verify drwxr-xr-x permissions
# If tmp upload dir has incorrect permissions, assume others do as well
# Verify drwx------ permissions
if File.stat(upload_path_tmp).mode == 040700 && File.owned?(upload_path_tmp)
puts "yes".green
else
puts "no".red
try_fixing_it(
"sudo chown -R #{gitlab_user} #{upload_path}",
"sudo find #{upload_path} -type f -exec chmod 0644 {} \\;",
"sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0755 {} \\;"
"sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
)
for_more_information(
see_installation_guide_section "GitLab"
......@@ -303,7 +304,7 @@ namespace :gitlab do
else
puts "no".red
try_fixing_it(
"sudo chmod 0750 #{upload_path}",
"sudo find #{upload_path} -type d -not -path #{upload_path} -exec chmod 0700 {} \\;"
)
for_more_information(
see_installation_guide_section "GitLab"
......
#!/bin/bash
# Sends Slack notification ERROR_MSG to CHANNEL
# An env. variable CI_SLACK_WEBHOOK_URL needs to be set.
CHANNEL=$1
ERROR_MSG=$2
if [ -z "$CHANNEL" ] || [ -z "$ERROR_MSG" ] || [ -z "$CI_SLACK_WEBHOOK_URL" ]; then
echo "Missing argument(s) - Use: $0 channel message"
echo "and set CI_SLACK_WEBHOOK_URL environment variable."
else
curl -X POST --data-urlencode 'payload={"channel": "'"$CHANNEL"'", "username": "gitlab-ci", "text": "'"$ERROR_MSG"'", "icon_emoji": ":gitlab:"}' "$CI_SLACK_WEBHOOK_URL"
fi
\ No newline at end of file
......@@ -53,6 +53,10 @@ FactoryGirl.define do
tag true
end
factory :ci_build_with_coverage do
coverage 99.9
end
trait :trace do
after(:create) do |build, evaluator|
build.trace = 'BUILD TRACE'
......@@ -68,7 +72,7 @@ FactoryGirl.define do
build.artifacts_metadata =
fixture_file_upload(Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'),
'application/x-gzip')
build.save!
end
end
......
......@@ -4,38 +4,68 @@ describe Ci::Status do
describe '.get_status' do
subject { described_class.get_status(statuses) }
[:ci_build, :generic_commit_status].each do |type|
context "for #{type}" do
context 'all successful' do
let(:statuses) { Array.new(2) { create(type, status: :success) } }
it { is_expected.to eq 'success' }
end
shared_examples 'build status summary' do
context 'all successful' do
let(:statuses) { Array.new(2) { create(type, status: :success) } }
it { is_expected.to eq 'success' }
end
context 'at least one failed' do
let(:statuses) { [create(type, status: :success), create(type, status: :failed)] }
it { is_expected.to eq 'failed' }
context 'at least one failed' do
let(:statuses) do
[create(type, status: :success), create(type, status: :failed)]
end
context 'at least one running' do
let(:statuses) { [create(type, status: :success), create(type, status: :running)] }
it { is_expected.to eq 'running' }
it { is_expected.to eq 'failed' }
end
context 'at least one running' do
let(:statuses) do
[create(type, status: :success), create(type, status: :running)]
end
context 'at least one pending' do
let(:statuses) { [create(type, status: :success), create(type, status: :pending)] }
it { is_expected.to eq 'running' }
it { is_expected.to eq 'running' }
end
context 'at least one pending' do
let(:statuses) do
[create(type, status: :success), create(type, status: :pending)]
end
context 'success and failed but allowed to fail' do
let(:statuses) { [create(type, status: :success), create(type, status: :failed, allow_failure: true)] }
it { is_expected.to eq 'success' }
it { is_expected.to eq 'running' }
end
context 'success and failed but allowed to fail' do
let(:statuses) do
[create(type, status: :success),
create(type, status: :failed, allow_failure: true)]
end
context 'one failed but allowed to fail' do
let(:statuses) { [create(type, status: :failed, allow_failure: true)] }
it { is_expected.to eq 'success' }
it { is_expected.to eq 'success' }
end
context 'one failed but allowed to fail' do
let(:statuses) { [create(type, status: :failed, allow_failure: true)] }
it { is_expected.to eq 'success' }
end
context 'one finished and second running but allowed to fail' do
let(:statuses) do
[create(type, status: :success),
create(type, status: :running, allow_failure: true)]
end
it { is_expected.to eq 'running' }
end
end
context 'ci build statuses' do
let(:type) { :ci_build }
it_behaves_like 'build status summary'
end
context 'generic commit statuses' do
let(:type) { :generic_commit_status }
it_behaves_like 'build status summary'
end
end
end
......@@ -37,20 +37,6 @@ describe Todo, models: true do
it { is_expected.to validate_presence_of(:user) }
end
describe '#action_name' do
it 'returns proper message when action is an assigment' do
subject.action = Todo::ASSIGNED
expect(subject.action_name).to eq 'assigned'
end
it 'returns proper message when action is a mention' do
subject.action = Todo::MENTIONED
expect(subject.action_name).to eq 'mentioned you on'
end
end
describe '#body' do
before do
subject.target = build(:issue, title: 'Bugfix')
......@@ -69,21 +55,15 @@ describe Todo, models: true do
end
end
describe '#target_iid' do
let(:issue) { build(:issue, id: 1, iid: 5) }
before do
subject.target = issue
end
it 'returns target.iid when target respond to iid' do
expect(subject.target_iid).to eq 5
describe '#done!' do
it 'changes state to done' do
todo = create(:todo, state: :pending)
expect { todo.done! }.to change(todo, :state).from('pending').to('done')
end
it 'returns target_id when target does not respond to iid' do
allow(issue).to receive(:respond_to?).with(:iid).and_return(false)
expect(subject.target_iid).to eq 1
it 'does not raise error when is already done' do
todo = create(:todo, state: :done)
expect { todo.done! }.not_to raise_error
end
end
end
......@@ -110,6 +110,8 @@ describe TodoService, services: true do
let!(:first_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
let!(:second_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) }
let(:note) { create(:note, project: project, noteable: issue, author: john_doe, note: mentions) }
let(:note_on_commit) { create(:note_on_commit, project: project, author: john_doe, note: mentions) }
let(:note_on_project_snippet) { create(:note_on_project_snippet, project: project, author: john_doe, note: mentions) }
let(:award_note) { create(:note, :award, project: project, noteable: issue, author: john_doe, note: 'thumbsup') }
let(:system_note) { create(:system_note, project: project, noteable: issue) }
......@@ -145,6 +147,14 @@ describe TodoService, services: true do
should_not_create_todo(user: john_doe, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
should_not_create_todo(user: stranger, target: issue, author: john_doe, action: Todo::MENTIONED, note: note)
end
it 'does not create todo when leaving a note on commit' do
should_not_create_any_todo { service.new_note(note_on_commit, john_doe) }
end
it 'does not create todo when leaving a note on snippet' do
should_not_create_any_todo { service.new_note(note_on_project_snippet, john_doe) }
end
end
end
......
......@@ -7,7 +7,7 @@ timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 90 : 10
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout)
Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768])
end
Capybara.default_wait_time = timeout
......
require 'rails_helper'
describe 'devise/shared/_signin_box' do
describe 'Crowd form' do
before do
stub_devise
assign(:ldap_servers, [])
end
it 'is shown when Crowd is enabled' do
enable_crowd
render
expect(rendered).to have_selector('#tab-crowd form')
end
it 'is not shown when Crowd is disabled' do
render
expect(rendered).not_to have_selector('#tab-crowd')
end
end
def stub_devise
allow(view).to receive(:devise_mapping).and_return(Devise.mappings[:user])
allow(view).to receive(:resource).and_return(spy)
allow(view).to receive(:resource_name).and_return(:user)
end
def enable_crowd
allow(view).to receive(:form_based_providers).and_return([:crowd])
allow(view).to receive(:crowd_enabled?).and_return(true)
allow(view).to receive(:user_omniauth_authorize_path).with('crowd').
and_return('/crowd')
end
end
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