Commit 3753c1e0 authored by James Lopez's avatar James Lopez

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into fix/cross-reference-notes-forks

parents f7c06ecd 10aa99a3
...@@ -137,23 +137,104 @@ bundler:audit: ...@@ -137,23 +137,104 @@ bundler:audit:
# Ruby 2.1 jobs # Ruby 2.1 jobs
spec:ruby21: spec:feature:ruby21:
image: ruby:2.1 image: ruby:2.1
only:
- master
script: script:
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null - RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
tags:
- ruby
- mysql
spec:api:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
tags:
- ruby
- mysql
spec:models:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
tags: tags:
- ruby - ruby
- mysql - mysql
spec:lib:ruby21:
image: ruby:2.1
only: only:
- master - master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
tags:
- ruby
- mysql
spinach:ruby21: spec:services:ruby21:
image: ruby:2.1 image: ruby:2.1
only:
- master
script: script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach - RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
tags: tags:
- ruby - ruby
- mysql - mysql
spec:benchmark:ruby21:
image: ruby:2.1
only: only:
- master - master
script:
- RAILS_ENV=test bundle exec rake spec:benchmark
tags:
- ruby
- mysql
allow_failure: true
spec:other:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
tags:
- ruby
- mysql
spinach:project:half:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
tags:
- ruby
- mysql
spinach:project:rest:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
tags:
- ruby
- mysql
spinach:other:ruby21:
image: ruby:2.1
only:
- master
script:
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
tags:
- ruby
- mysql
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.5.0 (unreleased) v 8.5.0 (unreleased)
- Cache various Repository methods to improve performance (Yorick Peterse)
- Ensure rake tasks that don't need a DB connection can be run without one - Ensure rake tasks that don't need a DB connection can be run without one
- Update New Relic gem to 3.14.1.311 (Stan Hu) - Update New Relic gem to 3.14.1.311 (Stan Hu)
- Add "visibility" flag to GET /projects api endpoint - Add "visibility" flag to GET /projects api endpoint
- Add an option to supply root email through an environmental variable (Koichiro Mikami)
- Ignore binary files in code search to prevent Error 500 (Stan Hu) - Ignore binary files in code search to prevent Error 500 (Stan Hu)
- Render sanitized SVG images (Stan Hu) - Render sanitized SVG images (Stan Hu)
- Support download access by PRIVATE-TOKEN header (Stan Hu) - Support download access by PRIVATE-TOKEN header (Stan Hu)
- Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push
- Add option to include the sender name in body of Notify email (Jason Lee)
- New UI for pagination - New UI for pagination
- Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet - Don't prevent sign out when 2FA enforcement is enabled and user hasn't yet
set it up set it up
...@@ -15,14 +18,18 @@ v 8.5.0 (unreleased) ...@@ -15,14 +18,18 @@ v 8.5.0 (unreleased)
- Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel)
- Fix label links for a merge request pointing to issues list - Fix label links for a merge request pointing to issues list
- Don't vendor minified JS - Don't vendor minified JS
- Increase project import timeout to 15 minutes
- Display 404 error on group not found - Display 404 error on group not found
- Track project import failure - Track project import failure
- Support Two-factor Authentication for LDAP users - Support Two-factor Authentication for LDAP users
- Display database type and version in Administration dashboard - Display database type and version in Administration dashboard
- Allow limited Markdown in Broadcast Messages
- Fix visibility level text in admin area (Zeger-Jan van de Weg) - Fix visibility level text in admin area (Zeger-Jan van de Weg)
- Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg) - Warn admin during OAuth of granting admin rights (Zeger-Jan van de Weg)
- Update the ExternalIssue regex pattern (Blake Hitchcock) - Update the ExternalIssue regex pattern (Blake Hitchcock)
- Remember user's inline/side-by-side diff view preference in a cookie (Kirill Katsnelson)
- Optimized performance of finding issues to be closed by a merge request - Optimized performance of finding issues to be closed by a merge request
- API: Expose MergeRequest#merge_status (Andrei Dziahel)
- Revert "Add IP check against DNSBLs at account sign-up" - Revert "Add IP check against DNSBLs at account sign-up"
- Fix API to keep request parameters in Link header (Michael Potthoff) - Fix API to keep request parameters in Link header (Michael Potthoff)
- Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead - Deprecate API "merge_request/:merge_request_id/comments". Use "merge_requests/:merge_request_id/notes" instead
...@@ -32,9 +39,19 @@ v 8.5.0 (unreleased) ...@@ -32,9 +39,19 @@ v 8.5.0 (unreleased)
- Support Akismet spam checking for creation of issues via API (Stan Hu) - Support Akismet spam checking for creation of issues via API (Stan Hu)
- Improve UI consistency between projects and groups lists - Improve UI consistency between projects and groups lists
- Add sort dropdown to dashboard projects page - Add sort dropdown to dashboard projects page
- Fixed logo animation on Safari (Roman Rott)
- Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg) - Hide remove source branch button when the MR is merged but new commits are pushed (Zeger-Jan van de Weg)
- In seach autocomplete show only groups and projects you are member of - In seach autocomplete show only groups and projects you are member of
- Don't process cross-reference notes from forks - Don't process cross-reference notes from forks
- Fix: init.d script not working on OS X
- Faster snippet search
- Title for milestones should be unique (Zeger-Jan van de Weg)
- Validate correctness of maximum attachment size application setting
v 8.4.4
- Update omniauth-saml gem to 1.4.2
- Prevent long-running backup tasks from timing out the database connection
- Add a Project setting to allow guests to view build logs (defaults to true)
v 8.4.3 v 8.4.3
- Increase lfs_objects size column to 8-byte integer to allow files larger - Increase lfs_objects size column to 8-byte integer to allow files larger
......
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
- [Contribute to GitLab](#contribute-to-gitlab)
- [Contributor license agreement](#contributor-license-agreement)
- [Security vulnerability disclosure](#security-vulnerability-disclosure)
- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
- [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute)
- [Issue tracker](#issue-tracker)
- [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines)
- [Issue weight](#issue-weight)
- [Regression issues](#regression-issues)
- [Merge requests](#merge-requests)
- [Merge request guidelines](#merge-request-guidelines)
- [Merge request description format](#merge-request-description-format)
- [Contribution acceptance criteria](#contribution-acceptance-criteria)
- [Changes for Stable Releases](#changes-for-stable-releases)
- [Definition of done](#definition-of-done)
- [Style guides](#style-guides)
- [Code of conduct](#code-of-conduct)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# Contribute to GitLab # Contribute to GitLab
Thank you for your interest in contributing to GitLab. This guide details how Thank you for your interest in contributing to GitLab. This guide details how
...@@ -234,15 +260,17 @@ request is as follows: ...@@ -234,15 +260,17 @@ request is as follows:
1. Add your changes to the [CHANGELOG](CHANGELOG) 1. Add your changes to the [CHANGELOG](CHANGELOG)
1. If you are changing the README, some documentation or other things which 1. If you are changing the README, some documentation or other things which
have no effect on the tests, add `[ci skip]` somewhere in the commit message have no effect on the tests, add `[ci skip]` somewhere in the commit message
and make sure to read the [documentation styleguide][doc-styleguide]
1. If you have multiple commits please combine them into one commit by 1. If you have multiple commits please combine them into one commit by
[squashing them][git-squash] [squashing them][git-squash]
1. Push the commit(s) to your fork 1. Push the commit(s) to your fork
1. Submit a merge request (MR) to the master branch 1. Submit a merge request (MR) to the master branch
1. The MR title should describe the change you want to make 1. The MR title should describe the change you want to make
1. The MR description should give a motive for your change and the method you 1. The MR description should give a motive for your change and the method you
used to achieve it used to achieve it, see the [merge request description format]
(#merge-request-description-format)
1. If the MR changes the UI it should include before and after screenshots 1. If the MR changes the UI it should include before and after screenshots
1. If the MR changes CSS classes please include the list of affected pages 1. If the MR changes CSS classes please include the list of affected pages,
`grep css-class ./app -R` `grep css-class ./app -R`
1. Link any relevant [issues][ce-tracker] in the merge request description and 1. Link any relevant [issues][ce-tracker] in the merge request description and
leave a comment on them with a link back to the MR leave a comment on them with a link back to the MR
...@@ -275,7 +303,55 @@ For examples of feedback on merge requests please look at already ...@@ -275,7 +303,55 @@ For examples of feedback on merge requests please look at already
request feel free to mention one of the Merge Marshalls of the [core team][]. request feel free to mention one of the Merge Marshalls of the [core team][].
Please ensure that your merge request meets the contribution acceptance criteria. Please ensure that your merge request meets the contribution acceptance criteria.
When having your code reviewed and when reviewing merge requests please take the [thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review) into account. When having your code reviewed and when reviewing merge requests please take the
[thoughtbot code review guidelines](https://github.com/thoughtbot/guides/tree/master/code-review)
into account.
### Merge request description format
Please submit merge requests using the following template in the merge request
description area. Copy-paste it to retain the markdown format.
```
## What does this MR do?
## Are there points in the code the reviewer needs to double check?
## Why was this MR needed?
## What are the relevant issue numbers?
## Screenshots (if relevant)
```
### Contribution acceptance criteria
1. The change is as small as possible
1. Include proper tests and make all tests pass (unless it contains a test
exposing a bug in existing code)
1. If you suspect a failing CI build is unrelated to your contribution, you may
try and restart the failing CI job or ask a developer to fix the
aforementioned failing test
1. Your MR initially contains a single commit (please use `git rebase -i` to
squash commits)
1. Your changes 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. 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 (e.g., 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. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options since they complicate future changes
1. Changes after submitting the merge request should be in separate commits
(no squashing). If necessary, you will be asked to squash when the review is
over, before merging.
1. It conforms to the [style guides](#style-guides) and the following:
- If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
- Don't touch neighbouring lines. As an exception, automatic mass
refactoring modifications may leave style non-compliant.
## Changes for Stable Releases ## Changes for Stable Releases
...@@ -298,7 +374,7 @@ the feature you contribute through all of these steps. ...@@ -298,7 +374,7 @@ the feature you contribute through all of these steps.
1. Description explaining the relevancy (see following item) 1. Description explaining the relevancy (see following item)
1. Working and clean code that is commented where needed 1. Working and clean code that is commented where needed
1. Unit and integration tests that pass on the CI server 1. Unit and integration tests that pass on the CI server
1. Documented in the /doc directory 1. [Documented][doc-styleguide] in the /doc directory
1. Changelog entry added 1. Changelog entry added
1. Reviewed and any concerns are addressed 1. Reviewed and any concerns are addressed
1. Merged by the project lead 1. Merged by the project lead
...@@ -319,43 +395,6 @@ merge request: ...@@ -319,43 +395,6 @@ merge request:
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh 1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab 1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
## Merge request description format
1. What does this MR do?
1. Are there points in the code the reviewer needs to double check?
1. Why was this MR needed?
1. What are the relevant issue numbers?
1. Screenshots (if relevant)
## Contribution acceptance criteria
1. The change is as small as possible (see the above paragraph for details)
1. Include proper tests and make all tests pass (unless it contains a test
exposing a bug in existing code)
1. If you suspect a failing CI build is unrelated to your contribution, you may
try and restart the failing CI job or ask a developer to fix the
aforementioned failing test
1. Your MR initially contains a single commit (please use `git rebase -i` to
squash commits)
1. Your changes 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. 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. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options since they complicate future changes
1. Changes after submitting the merge request should be in separate commits
(no squashing). If necessary, you will be asked to squash when the review is
over, before merging.
1. It conforms to the following style guides:
* If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
* Don't touch neighbouring lines. As an exception, automatic mass
refactoring modifications may leave style non-compliant.
## Style guides ## Style guides
1. [Ruby](https://github.com/bbatsov/ruby-style-guide). 1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
...@@ -370,7 +409,7 @@ merge request: ...@@ -370,7 +409,7 @@ merge request:
contributors to enhance security contributors to enhance security
1. [Database Migrations](doc/development/migration_style_guide.md) 1. [Database Migrations](doc/development/migration_style_guide.md)
1. [Markdown](http://www.cirosantilli.com/markdown-styleguide) 1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
1. [Documentation styleguide](doc/development/doc_styleguide.md) 1. [Documentation styleguide][doc-styleguide]
1. Interface text should be written subjectively instead of objectively. It 1. Interface text should be written subjectively instead of objectively. It
should be the GitLab core team addressing a person. It should be written in should be the GitLab core team addressing a person. It should be written in
present time and never use past tense (has been/was). For example instead present time and never use past tense (has been/was). For example instead
...@@ -411,7 +450,7 @@ reported by emailing `contact@gitlab.com`. ...@@ -411,7 +450,7 @@ 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][], version 1.1.0,
available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/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/ [core-team]: https://about.gitlab.com/core-team/
[getting help page]: https://about.gitlab.com/getting-help/ [getting help page]: https://about.gitlab.com/getting-help/
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq [Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs [up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
...@@ -432,3 +471,4 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor ...@@ -432,3 +471,4 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[Contributor Covenant]: http://contributor-covenant.org [Contributor Covenant]: http://contributor-covenant.org
[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout [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 [rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
...@@ -50,7 +50,7 @@ gem "browser", '~> 1.0.0' ...@@ -50,7 +50,7 @@ gem "browser", '~> 1.0.0'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", '~> 8.0.0' gem "gitlab_git", '~> 8.1'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
......
...@@ -357,7 +357,7 @@ GEM ...@@ -357,7 +357,7 @@ GEM
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab_emoji (0.2.0) gitlab_emoji (0.2.0)
gemojione (~> 2.1) gemojione (~> 2.1)
gitlab_git (8.0.0) gitlab_git (8.1.0)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.3)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
...@@ -932,7 +932,7 @@ DEPENDENCIES ...@@ -932,7 +932,7 @@ DEPENDENCIES
github-markup (~> 1.3.1) github-markup (~> 1.3.1)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab_emoji (~> 0.2.0) gitlab_emoji (~> 0.2.0)
gitlab_git (~> 8.0.0) gitlab_git (~> 8.1)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (~> 1.2.1) gitlab_omniauth-ldap (~> 1.2.1)
gollum-lib (~> 4.1.0) gollum-lib (~> 4.1.0)
......
...@@ -12,19 +12,6 @@ class @Admin ...@@ -12,19 +12,6 @@ class @Admin
e.preventDefault() e.preventDefault()
$('.js-toggle-colors-container').toggle() $('.js-toggle-colors-container').toggle()
$('input#broadcast_message_color').on 'input', ->
previewColor = $(@).val()
$('div.broadcast-message-preview').css('background-color', previewColor)
$('input#broadcast_message_font').on 'input', ->
previewColor = $(@).val()
$('div.broadcast-message-preview').css('color', previewColor)
$('textarea#broadcast_message_message').on 'input', ->
previewMessage = $(@).val()
previewMessage = "Your message here" if previewMessage.trim() == ''
$('div.broadcast-message-preview span').text(previewMessage)
$('.log-tabs a').click (e) -> $('.log-tabs a').click (e) ->
e.preventDefault() e.preventDefault()
$(this).tab('show') $(this).tab('show')
......
...@@ -211,23 +211,29 @@ $ -> ...@@ -211,23 +211,29 @@ $ ->
$this.attr 'value', $this.val() $this.attr 'value', $this.val()
return return
$(document).on 'keyup', 'input[type="search"]' , (e) -> $(document)
.off 'keyup', 'input[type="search"]'
.on 'keyup', 'input[type="search"]' , (e) ->
$this = $(this) $this = $(this)
$this.attr 'value', $this.val() $this.attr 'value', $this.val()
$(document).on 'breakpoint:change', (e, breakpoint) -> $(document)
.off 'breakpoint:change'
.on 'breakpoint:change', (e, breakpoint) ->
if breakpoint is 'sm' or breakpoint is 'xs' if breakpoint is 'sm' or breakpoint is 'xs'
$gutterIcon = $('.gutter-toggle').find('i') $gutterIcon = $('.gutter-toggle').find('i')
if $gutterIcon.hasClass('fa-angle-double-right') if $gutterIcon.hasClass('fa-angle-double-right')
$gutterIcon.closest('a').trigger('click') $gutterIcon.closest('a').trigger('click')
$(document)
$(document).on 'click', 'aside .gutter-toggle', (e) -> .off 'click', 'aside .gutter-toggle'
.on 'click', 'aside .gutter-toggle', (e) ->
e.preventDefault() e.preventDefault()
$this = $(this) $this = $(this)
$thisIcon = $this.find 'i' $thisIcon = $this.find 'i'
if $thisIcon.hasClass('fa-angle-double-right') if $thisIcon.hasClass('fa-angle-double-right')
$thisIcon.removeClass('fa-angle-double-right') $thisIcon
.removeClass('fa-angle-double-right')
.addClass('fa-angle-double-left') .addClass('fa-angle-double-left')
$this $this
.closest('aside') .closest('aside')
...@@ -237,7 +243,8 @@ $ -> ...@@ -237,7 +243,8 @@ $ ->
.removeClass('right-sidebar-expanded') .removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed') .addClass('right-sidebar-collapsed')
else else
$thisIcon.removeClass('fa-angle-double-left') $thisIcon
.removeClass('fa-angle-double-left')
.addClass('fa-angle-double-right') .addClass('fa-angle-double-right')
$this $this
.closest('aside') .closest('aside')
...@@ -282,7 +289,9 @@ $ -> ...@@ -282,7 +289,9 @@ $ ->
if bootstrapBreakpoint is "xs" or "sm" if bootstrapBreakpoint is "xs" or "sm"
$(document).trigger('breakpoint:change', [bootstrapBreakpoint]) $(document).trigger('breakpoint:change', [bootstrapBreakpoint])
$(window).on "resize", (e) -> $(window)
.off "resize"
.on "resize", (e) ->
fitSidebarForSize() fitSidebarForSize()
setBootstrapBreakpoints() setBootstrapBreakpoints()
......
$ ->
$('input#broadcast_message_color').on 'input', ->
previewColor = $(@).val()
$('div.broadcast-message-preview').css('background-color', previewColor)
$('input#broadcast_message_font').on 'input', ->
previewColor = $(@).val()
$('div.broadcast-message-preview').css('color', previewColor)
previewPath = $('textarea#broadcast_message_message').data('preview-path')
$('textarea#broadcast_message_message').on 'input', ->
message = $(@).val()
if message == ''
$('.js-broadcast-message-preview').text("Your message here")
else
$.ajax(
url: previewPath
type: "POST"
data: { broadcast_message: { message: message } }
)
class @Dashboard @Dashboard =
constructor: -> init: ->
new ProjectsList() $(".projects-list-filter").off('keyup')
this.initSearch()
initSearch: ->
@timer = null
$(".projects-list-filter").on('keyup', ->
clearTimeout(@timer)
@timer = setTimeout(Dashboard.filterResults, 500)
)
filterResults: =>
$('.projects-list-holder').fadeTo(250, 0.5)
form = null
form = $("form#project-filter-form")
search = $(".projects-list-filter").val()
project_filter_url = form.attr('action') + '?' + form.serialize()
$.ajax
type: "GET"
url: form.attr('action')
data: form.serialize()
complete: ->
$('.projects-list-holder').fadeTo(250, 1)
success: (data) ->
$('.projects-list-holder').replaceWith(data.html)
# Change url so if user reload a page - search results are saved
history.replaceState {page: project_filter_url}, document.title, project_filter_url
dataType: "json"
...@@ -16,6 +16,8 @@ class Dispatcher ...@@ -16,6 +16,8 @@ class Dispatcher
shortcut_handler = null shortcut_handler = null
switch page switch page
when 'explore:projects:index', 'explore:projects:starred', 'explore:projects:trending'
Dashboard.init()
when 'projects:issues:index' when 'projects:issues:index'
Issues.init() Issues.init()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
...@@ -58,7 +60,7 @@ class Dispatcher ...@@ -58,7 +60,7 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
MergeRequests.init() MergeRequests.init()
when 'dashboard:show', 'root:show' when 'dashboard:show', 'root:show'
new Dashboard() Dashboard.init()
when 'dashboard:activity' when 'dashboard:activity'
new Activities() new Activities()
when 'dashboard:projects:starred' when 'dashboard:projects:starred'
......
...@@ -42,3 +42,9 @@ work = -> ...@@ -42,3 +42,9 @@ work = ->
$(document).on('page:fetch', start) $(document).on('page:fetch', start)
$(document).on('page:change', stop) $(document).on('page:change', stop)
$ ->
# Make logo clickable as part of a workaround for Safari visited
# link behaviour (See !2690).
$('#logo').on 'click', ->
$('#js-shortcuts-home').get(0).click()
...@@ -3,24 +3,24 @@ class @ProjectsList ...@@ -3,24 +3,24 @@ class @ProjectsList
$(".projects-list .js-expand").on 'click', (e) -> $(".projects-list .js-expand").on 'click', (e) ->
e.preventDefault() e.preventDefault()
list = $(this).closest('.projects-list') list = $(this).closest('.projects-list')
list.find("li").show()
list.find("li.bottom").hide()
$(".projects-list-filter").keyup -> $("#filter_projects").on 'keyup', ->
terms = $(this).val() ProjectsList.filter_results($("#filter_projects"))
uiBox = $('div.projects-list-holder')
filterSelector = $(this).data('filter-selector') || 'span.filter-title'
if terms == "" || terms == undefined @filter_results: ($element) ->
uiBox.find("ul.projects-list li").show() terms = $element.val()
else filterSelector = $element.data('filter-selector') || 'span.filter-title'
uiBox.find("ul.projects-list li").each (index) ->
name = $(this).find(filterSelector).text()
if name.toLowerCase().search(terms.toLowerCase()) == -1 if not terms
$(this).hide() $(".projects-list li").show()
$('.gl-pagination').show()
else else
$(this).show() $(".projects-list li").each (index) ->
uiBox.find("ul.projects-list li.bottom").hide() $this = $(this)
name = $this.find(filterSelector).text()
if name.toLowerCase().indexOf(terms.toLowerCase()) == -1
$this.hide()
else
$this.show()
$('.gl-pagination').hide()
...@@ -16,12 +16,31 @@ class @ShortcutsIssuable extends ShortcutsNavigation ...@@ -16,12 +16,31 @@ class @ShortcutsIssuable extends ShortcutsNavigation
@replyWithSelectedText() @replyWithSelectedText()
return false return false
) )
Mousetrap.bind('j', =>
@prevIssue()
return false
)
Mousetrap.bind('k', =>
@nextIssue()
return false
)
if isMergeRequest if isMergeRequest
@enabledHelp.push('.hidden-shortcut.merge_requests') @enabledHelp.push('.hidden-shortcut.merge_requests')
else else
@enabledHelp.push('.hidden-shortcut.issues') @enabledHelp.push('.hidden-shortcut.issues')
prevIssue: ->
$prevBtn = $('.prev-btn')
if not $prevBtn.hasClass('disabled')
Turbolinks.visit($prevBtn.attr('href'))
nextIssue: ->
$nextBtn = $('.next-btn')
if not $nextBtn.hasClass('disabled')
Turbolinks.visit($nextBtn.attr('href'))
replyWithSelectedText: -> replyWithSelectedText: ->
if window.getSelection if window.getSelection
selected = window.getSelection().toString() selected = window.getSelection().toString()
......
...@@ -91,8 +91,17 @@ header { ...@@ -91,8 +91,17 @@ header {
.dropdown-toggle-caret { .dropdown-toggle-caret {
position: relative; position: relative;
top: -2px; top: -2px;
width: 12px;
line-height: 12px;
margin-left: 5px; margin-left: 5px;
font-size: 10px; font-size: 10px;
text-align: center;
cursor: pointer;
}
.project-item-select {
right: auto;
left: 0;
} }
} }
......
...@@ -85,6 +85,10 @@ ...@@ -85,6 +85,10 @@
display: inline-block; display: inline-block;
} }
> form {
display: inline-block;
}
input { input {
height: 34px; height: 34px;
display: inline-block; display: inline-block;
......
...@@ -45,6 +45,19 @@ ...@@ -45,6 +45,19 @@
overflow: hidden; overflow: hidden;
transition-duration: .3s; transition-duration: .3s;
.home {
z-index: 1;
position: absolute;
left: 0px;
}
#logo {
z-index: 2;
position: absolute;
width: 58px;
cursor: pointer;
}
a { a {
float: left; float: left;
height: $header-height; height: $header-height;
...@@ -70,7 +83,7 @@ ...@@ -70,7 +83,7 @@
width: 158px; width: 158px;
float: left; float: left;
margin: 0; margin: 0;
margin-left: 14px; margin-left: 50px;
font-size: 19px; font-size: 19px;
line-height: 41px; line-height: 41px;
font-weight: normal; font-weight: normal;
......
...@@ -13,8 +13,8 @@ $list-font-size: 15px; ...@@ -13,8 +13,8 @@ $list-font-size: 15px;
$sidebar_collapsed_width: 62px; $sidebar_collapsed_width: 62px;
$sidebar_width: 230px; $sidebar_width: 230px;
$gutter_collapsed_width: 62px; $gutter_collapsed_width: 62px;
$gutter_width: 312px; $gutter_width: 290px;
$gutter_inner_width: 280px; $gutter_inner_width: 258px;
$avatar_radius: 50%; $avatar_radius: 50%;
$code_font_size: 13px; $code_font_size: 13px;
$code_line_height: 1.5; $code_line_height: 1.5;
......
...@@ -55,6 +55,16 @@ ...@@ -55,6 +55,16 @@
@extend .alert-warning; @extend .alert-warning;
padding: 10px; padding: 10px;
text-align: center; text-align: center;
> div, p {
display: inline;
margin: 0;
a {
color: inherit;
text-decoration: underline;
}
}
} }
.broadcast-message-preview { .broadcast-message-preview {
......
...@@ -29,17 +29,6 @@ ...@@ -29,17 +29,6 @@
} }
} }
.project-issuable-filter {
.controls {
float: right;
margin-top: 11px;
}
.nav-links {
text-align: left;
}
}
.issuable-details { .issuable-details {
section { section {
.issuable-discussion { .issuable-discussion {
...@@ -244,3 +233,9 @@ ...@@ -244,3 +233,9 @@
} }
} }
} }
.detail-page-description {
small {
color: $gray-darkest;
}
}
\ No newline at end of file
...@@ -81,6 +81,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -81,6 +81,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:sentry_dsn, :sentry_dsn,
:akismet_enabled, :akismet_enabled,
:akismet_api_key, :akismet_api_key,
:email_author_in_body,
restricted_visibility_levels: [], restricted_visibility_levels: [],
import_sources: [] import_sources: []
) )
......
...@@ -2,7 +2,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -2,7 +2,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
before_action :finder, only: [:edit, :update, :destroy] before_action :finder, only: [:edit, :update, :destroy]
def index def index
@broadcast_messages = BroadcastMessage.reorder("starts_at ASC").page(params[:page]) @broadcast_messages = BroadcastMessage.reorder("ends_at DESC").page(params[:page])
@broadcast_message = BroadcastMessage.new @broadcast_message = BroadcastMessage.new
end end
...@@ -36,6 +36,10 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -36,6 +36,10 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
end end
end end
def preview
@message = broadcast_message_params[:message]
end
protected protected
def finder def finder
......
...@@ -277,9 +277,10 @@ class ApplicationController < ActionController::Base ...@@ -277,9 +277,10 @@ class ApplicationController < ActionController::Base
} }
end end
def view_to_html_string(partial) def view_to_html_string(partial, locals = {})
render_to_string( render_to_string(
partial, partial,
locals: locals,
layout: false, layout: false,
formats: [:html] formats: [:html]
) )
......
...@@ -3,52 +3,5 @@ module Ci ...@@ -3,52 +3,5 @@ module Ci
def self.railtie_helpers_paths def self.railtie_helpers_paths
"app/helpers/ci" "app/helpers/ci"
end end
private
def authorize_access_project!
unless can?(current_user, :read_project, project)
return page_404
end
end
def authorize_manage_builds!
unless can?(current_user, :manage_builds, project)
return page_404
end
end
def authenticate_admin!
return render_404 unless current_user.is_admin?
end
def authorize_manage_project!
unless can?(current_user, :admin_project, project)
return page_404
end
end
def page_404
render file: "#{Rails.root}/public/404.html", status: 404, layout: false
end
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
end
# JSON for infinite scroll via Pager object
def pager_json(partial, count)
html = render_to_string(
partial,
layout: false,
formats: [:html]
)
render json: {
html: html,
count: count
}
end
end end
end end
module Ci module Ci
class ProjectsController < Ci::ApplicationController class ProjectsController < Ci::ApplicationController
before_action :project, except: [:index] before_action :project
before_action :authenticate_user!, except: [:index, :build, :badge] before_action :authorize_read_project!, except: [:badge]
before_action :authorize_access_project!, except: [:index, :badge]
before_action :no_cache, only: [:badge] before_action :no_cache, only: [:badge]
protect_from_forgery protect_from_forgery
......
...@@ -5,6 +5,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -5,6 +5,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = current_user.authorized_projects.sorted_by_activity.non_archived
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
terms = params['filter_projects']
if terms.present?
@projects = @projects.search(terms)
end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank?
@last_push = current_user.recent_push @last_push = current_user.recent_push
respond_to do |format| respond_to do |format|
...@@ -14,6 +22,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -14,6 +22,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
load_events load_events
render layout: false render layout: false
end end
format.json do
render json: {
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end
end end
end end
...@@ -21,6 +34,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -21,6 +34,14 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = current_user.starred_projects @projects = current_user.starred_projects
@projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
terms = params['filter_projects']
if terms.present?
@projects = @projects.search(terms)
end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank?
@last_push = current_user.recent_push @last_push = current_user.recent_push
@groups = [] @groups = []
...@@ -28,8 +49,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -28,8 +49,9 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
format.html format.html
format.json do format.json do
load_events render json: {
pager_json("events/_events", @events.count) html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end end
end end
end end
......
...@@ -6,19 +6,49 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -6,19 +6,49 @@ class Explore::ProjectsController < Explore::ApplicationController
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.non_archived @projects = @projects.non_archived
@projects = @projects.search(params[:search]) if params[:search].present? @projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE) @projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end
end
end end
def trending def trending
@trending_projects = TrendingProjectsFinder.new.execute(current_user) @projects = TrendingProjectsFinder.new.execute(current_user)
@trending_projects = @trending_projects.non_archived @projects = @projects.non_archived
@trending_projects = @trending_projects.page(params[:page]).per(PER_PAGE) @projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end
end
end end
def starred def starred
@starred_projects = ProjectsFinder.new.execute(current_user) @projects = ProjectsFinder.new.execute(current_user)
@starred_projects = @starred_projects.reorder('star_count DESC') @projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@starred_projects = @starred_projects.page(params[:page]).per(PER_PAGE) @projects = @projects.reorder('star_count DESC')
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
respond_to do |format|
format.html
format.json do
render json: {
html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end
end
end end
end end
...@@ -14,7 +14,7 @@ class GroupsController < Groups::ApplicationController ...@@ -14,7 +14,7 @@ class GroupsController < Groups::ApplicationController
# Load group projects # Load group projects
before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete] before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete]
before_action :event_filter, only: :show before_action :event_filter, only: [:show, :events]
layout :determine_layout layout :determine_layout
...@@ -41,13 +41,16 @@ class GroupsController < Groups::ApplicationController ...@@ -41,13 +41,16 @@ class GroupsController < Groups::ApplicationController
def show def show
@last_push = current_user.recent_push if current_user @last_push = current_user.recent_push if current_user
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
respond_to do |format| respond_to do |format|
format.html format.html
format.json do format.json do
load_events render json: {
pager_json("events/_events", @events.count) html: view_to_html_string("dashboard/projects/_projects", locals: { projects: @projects })
}
end end
format.atom do format.atom do
...@@ -57,6 +60,15 @@ class GroupsController < Groups::ApplicationController ...@@ -57,6 +60,15 @@ class GroupsController < Groups::ApplicationController
end end
end end
def events
respond_to do |format|
format.json do
load_events
pager_json("events/_events", @events.count)
end
end
end
def edit def edit
end end
......
...@@ -28,6 +28,11 @@ class Projects::ApplicationController < ApplicationController ...@@ -28,6 +28,11 @@ class Projects::ApplicationController < ApplicationController
private private
def apply_diff_view_cookie!
view = params[:view] || cookies[:diff_view]
cookies.permanent[:diff_view] = params[:view] = view if view
end
def builds_enabled def builds_enabled
return render_404 unless @project.builds_enabled? return render_404 unless @project.builds_enabled?
end end
......
class Projects::ArtifactsController < Projects::ApplicationController class Projects::ArtifactsController < Projects::ApplicationController
layout 'project' layout 'project'
before_action :authorize_read_build_artifacts! before_action :authorize_read_build!
def download def download
unless artifacts_file.file_storage? unless artifacts_file.file_storage?
...@@ -43,14 +43,4 @@ class Projects::ArtifactsController < Projects::ApplicationController ...@@ -43,14 +43,4 @@ class Projects::ArtifactsController < Projects::ApplicationController
def artifacts_file def artifacts_file
@artifacts_file ||= build.artifacts_file @artifacts_file ||= build.artifacts_file
end end
def authorize_read_build_artifacts!
unless can?(current_user, :read_build_artifacts, @project)
if current_user.nil?
return authenticate_user!
else
return render_404
end
end
end
end end
class Projects::BuildsController < Projects::ApplicationController class Projects::BuildsController < Projects::ApplicationController
before_action :build, except: [:index, :cancel_all] before_action :build, except: [:index, :cancel_all]
before_action :authorize_manage_builds!, except: [:index, :show, :status] before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry]
before_action :authorize_update_build!, except: [:index, :show, :status]
layout "project" layout "project"
...@@ -69,10 +70,4 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -69,10 +70,4 @@ class Projects::BuildsController < Projects::ApplicationController
def build_path(build) def build_path(build)
namespace_project_build_path(build.project.namespace, build.project, build) namespace_project_build_path(build.project.namespace, build.project, build)
end end
def authorize_manage_builds!
unless can?(current_user, :manage_builds, project)
return render_404
end
end
end end
...@@ -4,15 +4,17 @@ ...@@ -4,15 +4,17 @@
class Projects::CommitController < Projects::ApplicationController class Projects::CommitController < Projects::ApplicationController
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_download_code!, except: [:cancel_builds] before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
before_action :authorize_manage_builds!, only: [:cancel_builds] before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
before_action :authorize_read_commit_status!, only: [:builds]
before_action :commit before_action :commit
before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds]
before_action :define_show_vars, only: [:show, :builds] before_action :define_show_vars, only: [:show, :builds]
def show def show
return git_not_found! unless @commit return git_not_found! unless @commit
apply_diff_view_cookie!
@line_notes = commit.notes.inline @line_notes = commit.notes.inline
@note = @project.build_commit_note(commit) @note = @project.build_commit_note(commit)
@notes = commit.notes.not_inline.fresh @notes = commit.notes.not_inline.fresh
...@@ -77,10 +79,4 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -77,10 +79,4 @@ class Projects::CommitController < Projects::ApplicationController
@statuses = ci_commit.statuses if ci_commit @statuses = ci_commit.statuses if ci_commit
end end
def authorize_manage_builds!
unless can?(current_user, :manage_builds, project)
return render_404
end
end
end end
...@@ -57,6 +57,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -57,6 +57,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def diffs def diffs
apply_diff_view_cookie!
@commit = @merge_request.last_commit @commit = @merge_request.last_commit
@base_commit = @merge_request.diff_base_commit @base_commit = @merge_request.diff_base_commit
......
class Projects::RunnerProjectsController < Projects::ApplicationController class Projects::RunnerProjectsController < Projects::ApplicationController
before_action :authorize_admin_project! before_action :authorize_admin_build!
layout 'project_settings' layout 'project_settings'
......
class Projects::RunnersController < Projects::ApplicationController class Projects::RunnersController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show] before_action :set_runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
before_action :authorize_admin_project!
layout 'project_settings' layout 'project_settings'
......
class Projects::TriggersController < Projects::ApplicationController class Projects::TriggersController < Projects::ApplicationController
before_action :authorize_admin_project! before_action :authorize_admin_build!
layout 'project_settings' layout 'project_settings'
......
class Projects::VariablesController < Projects::ApplicationController class Projects::VariablesController < Projects::ApplicationController
before_action :authorize_admin_project! before_action :authorize_admin_build!
layout 'project_settings' layout 'project_settings'
......
...@@ -227,6 +227,7 @@ class ProjectsController < ApplicationController ...@@ -227,6 +227,7 @@ class ProjectsController < ApplicationController
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
:wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
:builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex,
:public_builds,
) )
end end
......
...@@ -6,6 +6,7 @@ class UsersController < ApplicationController ...@@ -6,6 +6,7 @@ class UsersController < ApplicationController
@contributed_projects = contributed_projects.joined(@user).reject(&:forked?) @contributed_projects = contributed_projects.joined(@user).reject(&:forked?)
@projects = PersonalProjectsFinder.new(@user).execute(current_user) @projects = PersonalProjectsFinder.new(@user).execute(current_user)
@projects = @projects.page(params[:page]).per(PER_PAGE)
@groups = @user.groups.order_id_desc @groups = @user.groups.order_id_desc
......
...@@ -3,7 +3,7 @@ module BroadcastMessagesHelper ...@@ -3,7 +3,7 @@ module BroadcastMessagesHelper
return unless message.present? return unless message.present?
content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do
icon('bullhorn') << ' ' << message.message icon('bullhorn') << ' ' << render_broadcast_message(message.message)
end end
end end
...@@ -31,4 +31,8 @@ module BroadcastMessagesHelper ...@@ -31,4 +31,8 @@ module BroadcastMessagesHelper
'Pending' 'Pending'
end end
end end
def render_broadcast_message(message)
Banzai.render(message, pipeline: :broadcast_message).html_safe
end
end end
...@@ -32,8 +32,10 @@ module NavHelper ...@@ -32,8 +32,10 @@ module NavHelper
end end
def page_gutter_class def page_gutter_class
if current_path?('merge_requests#show') ||
if current_path?('merge_requests#show') || current_path?('issues#show') current_path?('merge_requests#diffs') ||
current_path?('merge_requests#commits') ||
current_path?('issues#show')
if cookies[:collapsed_gutter] == 'true' if cookies[:collapsed_gutter] == 'true'
"page-gutter right-sidebar-collapsed" "page-gutter right-sidebar-collapsed"
else else
......
...@@ -59,9 +59,8 @@ module ProjectsHelper ...@@ -59,9 +59,8 @@ module ProjectsHelper
link_to(simple_sanitize(owner.name), user_path(owner)) link_to(simple_sanitize(owner.name), user_path(owner))
end end
project_link = link_to project_path(project), { class: "project-item-select-holder #{"js-projects-dropdown-toggle" if current_user}" } do project_link = link_to project_path(project), { class: "project-item-select-holder" } do
link_output = simple_sanitize(project.name) link_output = simple_sanitize(project.name)
link_output += content_tag :span, nil, { class: "fa fa-chevron-down dropdown-toggle-caret" } if current_user
if current_user if current_user
link_output += project_select_tag :project_path, link_output += project_select_tag :project_path,
...@@ -71,6 +70,7 @@ module ProjectsHelper ...@@ -71,6 +70,7 @@ module ProjectsHelper
link_output link_output
end end
project_link += icon "chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle" if current_user
full_title = namespace_link + ' / ' + project_link full_title = namespace_link + ' / ' + project_link
full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name full_title += ' &middot; '.html_safe + link_to(simple_sanitize(name), url) if name
...@@ -141,7 +141,7 @@ module ProjectsHelper ...@@ -141,7 +141,7 @@ module ProjectsHelper
nav_tabs << :merge_requests nav_tabs << :merge_requests
end end
if project.builds_enabled? && can?(current_user, :read_build, project) if can?(current_user, :read_build, project)
nav_tabs << :builds nav_tabs << :builds
end end
......
...@@ -33,7 +33,7 @@ module SnippetsHelper ...@@ -33,7 +33,7 @@ module SnippetsHelper
# surrounding code. # surrounding code.
# #
# @returns Array, unique and sorted. # @returns Array, unique and sorted.
def matching_lines(lined_content, surrounding_lines) def matching_lines(lined_content, surrounding_lines, query)
used_lines = [] used_lines = []
lined_content.each_with_index do |line, line_number| lined_content.each_with_index do |line, line_number|
used_lines.concat bounded_line_numbers( used_lines.concat bounded_line_numbers(
...@@ -51,9 +51,9 @@ module SnippetsHelper ...@@ -51,9 +51,9 @@ module SnippetsHelper
# surrounding_lines() worth of unmatching lines. # surrounding_lines() worth of unmatching lines.
# #
# @returns a hash with {snippet_object, snippet_chunks:{data,start_line}} # @returns a hash with {snippet_object, snippet_chunks:{data,start_line}}
def chunk_snippet(snippet, surrounding_lines = 3) def chunk_snippet(snippet, query, surrounding_lines = 3)
lined_content = snippet.content.split("\n") lined_content = snippet.content.split("\n")
used_lines = matching_lines(lined_content, surrounding_lines) used_lines = matching_lines(lined_content, surrounding_lines, query)
snippet_chunk = [] snippet_chunk = []
snippet_chunks = [] snippet_chunks = []
......
...@@ -5,17 +5,18 @@ class Ability ...@@ -5,17 +5,18 @@ class Ability
return [] unless user.is_a?(User) return [] unless user.is_a?(User)
return [] if user.blocked? return [] if user.blocked?
case subject.class.name case subject
when "Project" then project_abilities(user, subject) when CommitStatus then commit_status_abilities(user, subject)
when "Issue" then issue_abilities(user, subject) when Project then project_abilities(user, subject)
when "Note" then note_abilities(user, subject) when Issue then issue_abilities(user, subject)
when "ProjectSnippet" then project_snippet_abilities(user, subject) when Note then note_abilities(user, subject)
when "PersonalSnippet" then personal_snippet_abilities(user, subject) when ProjectSnippet then project_snippet_abilities(user, subject)
when "MergeRequest" then merge_request_abilities(user, subject) when PersonalSnippet then personal_snippet_abilities(user, subject)
when "Group" then group_abilities(user, subject) when MergeRequest then merge_request_abilities(user, subject)
when "Namespace" then namespace_abilities(user, subject) when Group then group_abilities(user, subject)
when "GroupMember" then group_member_abilities(user, subject) when Namespace then namespace_abilities(user, subject)
when "ProjectMember" then project_member_abilities(user, subject) when GroupMember then group_member_abilities(user, subject)
when ProjectMember then project_member_abilities(user, subject)
else [] else []
end.concat(global_abilities(user)) end.concat(global_abilities(user))
end end
...@@ -25,6 +26,8 @@ class Ability ...@@ -25,6 +26,8 @@ class Ability
case true case true
when subject.is_a?(PersonalSnippet) when subject.is_a?(PersonalSnippet)
anonymous_personal_snippet_abilities(subject) anonymous_personal_snippet_abilities(subject)
when subject.is_a?(CommitStatus)
anonymous_commit_status_abilities(subject)
when subject.is_a?(Project) || subject.respond_to?(:project) when subject.is_a?(Project) || subject.respond_to?(:project)
anonymous_project_abilities(subject) anonymous_project_abilities(subject)
when subject.is_a?(Group) || subject.respond_to?(:group) when subject.is_a?(Group) || subject.respond_to?(:group)
...@@ -52,16 +55,26 @@ class Ability ...@@ -52,16 +55,26 @@ class Ability
:read_project_member, :read_project_member,
:read_merge_request, :read_merge_request,
:read_note, :read_note,
:read_build, :read_commit_status,
:download_code :download_code
] ]
# Allow to read builds by anonymous user if guests are allowed
rules << :read_build if project.public_builds?
rules - project_disabled_features_rules(project) rules - project_disabled_features_rules(project)
else else
[] []
end end
end end
def anonymous_commit_status_abilities(subject)
rules = anonymous_project_abilities(subject.project)
# If subject is Ci::Build which inherits from CommitStatus filter the abilities
rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build)
rules
end
def anonymous_group_abilities(subject) def anonymous_group_abilities(subject)
group = if subject.is_a?(Group) group = if subject.is_a?(Group)
subject subject
...@@ -113,6 +126,9 @@ class Ability ...@@ -113,6 +126,9 @@ class Ability
if project.public? || project.internal? if project.public? || project.internal?
rules.push(*public_project_rules) rules.push(*public_project_rules)
# Allow to read builds for internal projects
rules << :read_build if project.public_builds?
end end
if project.owner == user || user.admin? if project.owner == user || user.admin?
...@@ -134,7 +150,8 @@ class Ability ...@@ -134,7 +150,8 @@ class Ability
def public_project_rules def public_project_rules
@public_project_rules ||= project_guest_rules + [ @public_project_rules ||= project_guest_rules + [
:download_code, :download_code,
:fork_project :fork_project,
:read_commit_status,
] ]
end end
...@@ -149,7 +166,6 @@ class Ability ...@@ -149,7 +166,6 @@ class Ability
:read_project_member, :read_project_member,
:read_merge_request, :read_merge_request,
:read_note, :read_note,
:read_build,
:create_project, :create_project,
:create_issue, :create_issue,
:create_note :create_note
...@@ -158,24 +174,26 @@ class Ability ...@@ -158,24 +174,26 @@ class Ability
def project_report_rules def project_report_rules
@project_report_rules ||= project_guest_rules + [ @project_report_rules ||= project_guest_rules + [
:create_commit_status,
:read_commit_statuses,
:read_build_artifacts,
:download_code, :download_code,
:fork_project, :fork_project,
:create_project_snippet, :create_project_snippet,
:update_issue, :update_issue,
:admin_issue, :admin_issue,
:admin_label :admin_label,
:read_commit_status,
:read_build,
] ]
end end
def project_dev_rules def project_dev_rules
@project_dev_rules ||= project_report_rules + [ @project_dev_rules ||= project_report_rules + [
:admin_merge_request, :admin_merge_request,
:create_commit_status,
:update_commit_status,
:create_build,
:update_build,
:create_merge_request, :create_merge_request,
:create_wiki, :create_wiki,
:manage_builds,
:push_code :push_code
] ]
end end
...@@ -201,7 +219,9 @@ class Ability ...@@ -201,7 +219,9 @@ class Ability
:admin_merge_request, :admin_merge_request,
:admin_note, :admin_note,
:admin_wiki, :admin_wiki,
:admin_project :admin_project,
:admin_commit_status,
:admin_build
] ]
end end
...@@ -240,6 +260,10 @@ class Ability ...@@ -240,6 +260,10 @@ class Ability
rules += named_abilities('wiki') rules += named_abilities('wiki')
end end
unless project.builds_enabled
rules += named_abilities('build')
end
rules rules
end end
...@@ -376,6 +400,22 @@ class Ability ...@@ -376,6 +400,22 @@ class Ability
rules rules
end end
def commit_status_abilities(user, subject)
rules = project_abilities(user, subject.project)
# If subject is Ci::Build which inherits from CommitStatus filter the abilities
rules = filter_build_abilities(rules) if subject.is_a?(Ci::Build)
rules
end
def filter_build_abilities(rules)
# If we can't read build we should also not have that
# ability when looking at this in context of commit_status
%w(read create update admin).each do |rule|
rules.delete(:"#{rule}_commit_status") unless rules.include?(:"#{rule}_build")
end
rules
end
def abilities def abilities
@abilities ||= begin @abilities ||= begin
abilities = Six.new abilities = Six.new
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
# metrics_port :integer default(8089) # metrics_port :integer default(8089)
# sentry_enabled :boolean default(FALSE) # sentry_enabled :boolean default(FALSE)
# sentry_dsn :string # sentry_dsn :string
# email_author_in_body :boolean default(FALSE)
# #
class ApplicationSetting < ActiveRecord::Base class ApplicationSetting < ActiveRecord::Base
...@@ -92,6 +93,10 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -92,6 +93,10 @@ class ApplicationSetting < ActiveRecord::Base
presence: true, presence: true,
if: :akismet_enabled if: :akismet_enabled
validates :max_attachment_size,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
validates_each :restricted_visibility_levels do |record, attr, value| validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil? unless value.nil?
value.each do |level| value.each do |level|
......
...@@ -49,7 +49,7 @@ class Event < ActiveRecord::Base ...@@ -49,7 +49,7 @@ class Event < ActiveRecord::Base
scope :code_push, -> { where(action: PUSHED) } scope :code_push, -> { where(action: PUSHED) }
scope :in_projects, ->(projects) do scope :in_projects, ->(projects) do
where(project_id: projects.select(:id).reorder(nil)).recent where(project_id: projects.map(&:id)).recent
end end
scope :with_associations, -> { includes(project: :namespace) } scope :with_associations, -> { includes(project: :namespace) }
......
...@@ -34,7 +34,7 @@ class Milestone < ActiveRecord::Base ...@@ -34,7 +34,7 @@ class Milestone < ActiveRecord::Base
scope :closed, -> { with_state(:closed) } scope :closed, -> { with_state(:closed) }
scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_projects, ->(ids) { where(project_id: ids) }
validates :title, presence: true validates :title, presence: true, uniqueness: { scope: :project_id }
validates :project, presence: true validates :project, presence: true
strip_attributes :title strip_attributes :title
......
...@@ -790,6 +790,8 @@ class Project < ActiveRecord::Base ...@@ -790,6 +790,8 @@ class Project < ActiveRecord::Base
def change_head(branch) def change_head(branch)
# Cached divergent commit counts are based on repository head # Cached divergent commit counts are based on repository head
repository.expire_branch_cache repository.expire_branch_cache
repository.expire_root_ref_cache
gitlab_shell.update_repository_head(self.path_with_namespace, branch) gitlab_shell.update_repository_head(self.path_with_namespace, branch)
reload_default_branch reload_default_branch
end end
......
...@@ -44,7 +44,9 @@ class Repository ...@@ -44,7 +44,9 @@ class Repository
end end
def empty? def empty?
raw_repository.empty? return @empty unless @empty.nil?
@empty = cache.fetch(:empty?) { raw_repository.empty? }
end end
# #
...@@ -57,8 +59,12 @@ class Repository ...@@ -57,8 +59,12 @@ class Repository
# This method return true if repository contains some content visible in project page. # This method return true if repository contains some content visible in project page.
# #
def has_visible_content? def has_visible_content?
return @has_visible_content unless @has_visible_content.nil?
@has_visible_content = cache.fetch(:has_visible_content?) do
raw_repository.branch_count > 0 raw_repository.branch_count > 0
end end
end
def commit(id = 'HEAD') def commit(id = 'HEAD')
return nil unless raw_repository return nil unless raw_repository
...@@ -184,8 +190,11 @@ class Repository ...@@ -184,8 +190,11 @@ class Repository
cache.fetch(:"diverging_commit_counts_#{branch.name}") do cache.fetch(:"diverging_commit_counts_#{branch.name}") do
# Rugged seems to throw a `ReferenceError` when given branch_names rather # Rugged seems to throw a `ReferenceError` when given branch_names rather
# than SHA-1 hashes # than SHA-1 hashes
number_commits_behind = commits_between(branch.target, root_ref_hash).size number_commits_behind = raw_repository.
number_commits_ahead = commits_between(root_ref_hash, branch.target).size count_commits_between(branch.target, root_ref_hash)
number_commits_ahead = raw_repository.
count_commits_between(root_ref_hash, branch.target)
{ behind: number_commits_behind, ahead: number_commits_ahead } { behind: number_commits_behind, ahead: number_commits_ahead }
end end
...@@ -196,12 +205,6 @@ class Repository ...@@ -196,12 +205,6 @@ class Repository
readme version contribution_guide changelog license) readme version contribution_guide changelog license)
end end
def branch_cache_keys
branches.map do |branch|
:"diverging_commit_counts_#{branch.name}"
end
end
def build_cache def build_cache
cache_keys.each do |key| cache_keys.each do |key|
unless cache.exist?(key) unless cache.exist?(key)
...@@ -226,18 +229,37 @@ class Repository ...@@ -226,18 +229,37 @@ class Repository
@branches = nil @branches = nil
end end
def expire_cache def expire_cache(branch_name = nil)
cache_keys.each do |key| cache_keys.each do |key|
cache.expire(key) cache.expire(key)
end end
expire_branch_cache expire_branch_cache(branch_name)
end end
def expire_branch_cache def expire_branch_cache(branch_name = nil)
# When we push to the root branch we have to flush the cache for all other
# branches as their statistics are based on the commits relative to the
# root branch.
if !branch_name || branch_name == root_ref
branches.each do |branch| branches.each do |branch|
cache.expire(:"diverging_commit_counts_#{branch.name}") cache.expire(:"diverging_commit_counts_#{branch.name}")
end end
# In case a commit is pushed to a non-root branch we only have to flush the
# cache for said branch.
else
cache.expire(:"diverging_commit_counts_#{branch_name}")
end
end
def expire_root_ref_cache
cache.expire(:root_ref)
@root_ref = nil
end
def expire_has_visible_content_cache
cache.expire(:has_visible_content?)
@has_visible_content = nil
end end
def rebuild_cache def rebuild_cache
...@@ -477,7 +499,7 @@ class Repository ...@@ -477,7 +499,7 @@ class Repository
end end
def root_ref def root_ref
@root_ref ||= raw_repository.root_ref @root_ref ||= cache.fetch(:root_ref) { raw_repository.root_ref }
end end
def commit_dir(user, path, message, branch) def commit_dir(user, path, message, branch)
......
...@@ -18,18 +18,23 @@ class GitPushService ...@@ -18,18 +18,23 @@ class GitPushService
def execute(project, user, oldrev, newrev, ref) def execute(project, user, oldrev, newrev, ref)
@project, @user = project, user @project, @user = project, user
project.repository.expire_cache branch_name = Gitlab::Git.ref_name(ref)
project.repository.expire_cache(branch_name)
if push_remove_branch?(ref, newrev) if push_remove_branch?(ref, newrev)
project.repository.expire_has_visible_content_cache
@push_commits = [] @push_commits = []
elsif push_to_new_branch?(ref, oldrev) elsif push_to_new_branch?(ref, oldrev)
project.repository.expire_has_visible_content_cache
# Re-find the pushed commits. # Re-find the pushed commits.
if is_default_branch?(ref) if is_default_branch?(ref)
# Initial push to the default branch. Take the full history of that branch as "newly pushed". # Initial push to the default branch. Take the full history of that branch as "newly pushed".
@push_commits = project.repository.commits(newrev) @push_commits = project.repository.commits(newrev)
# Ensure HEAD points to the default branch in case it is not master # Ensure HEAD points to the default branch in case it is not master
branch_name = Gitlab::Git.ref_name(ref)
project.change_head(branch_name) project.change_head(branch_name)
# Set protection on the default branch if configured # Set protection on the default branch if configured
......
...@@ -47,6 +47,16 @@ ...@@ -47,6 +47,16 @@
= f.label :version_check_enabled do = f.label :version_check_enabled do
= f.check_box :version_check_enabled = f.check_box :version_check_enabled
Version check enabled Version check enabled
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :email_author_in_body do
= f.check_box :email_author_in_body
Include author name in notification email body
.help-block
Some email servers do not support overriding the email sender name.
Enable this option to include the name of the author of the issue,
merge request or comment in the email body instead.
.form-group .form-group
= f.label :admin_notification_email, class: 'control-label col-sm-2' = f.label :admin_notification_email, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
......
.broadcast-message-preview{ style: broadcast_message_style(@broadcast_message) } .broadcast-message-preview{ style: broadcast_message_style(@broadcast_message) }
= icon('bullhorn') = icon('bullhorn')
%span= @broadcast_message.message || "Your message here" .js-broadcast-message-preview
= render_broadcast_message(@broadcast_message.message.presence || "Your message here")
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-requires-input'} do |f| = form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-requires-input'} do |f|
-if @broadcast_message.errors.any? -if @broadcast_message.errors.any?
...@@ -10,7 +11,9 @@ ...@@ -10,7 +11,9 @@
.form-group .form-group
= f.label :message, class: 'control-label' = f.label :message, class: 'control-label'
.col-sm-10 .col-sm-10
= f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true = f.text_area :message, class: "form-control js-quick-submit js-autosize",
required: true,
data: { preview_path: preview_admin_broadcast_messages_path }
.form-group.js-toggle-colors-container .form-group.js-toggle-colors-container
.col-sm-10.col-sm-offset-2 .col-sm-10.col-sm-offset-2
= link_to 'Customize colors', '#', class: 'js-toggle-colors-link' = link_to 'Customize colors', '#', class: 'js-toggle-colors-link'
......
...@@ -34,4 +34,4 @@ ...@@ -34,4 +34,4 @@
= link_to icon('pencil-square-o'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-xs' = link_to icon('pencil-square-o'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-xs'
= link_to icon('times'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-xs btn-danger' = link_to icon('times'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-xs btn-danger'
= paginate @broadcast_messages = paginate @broadcast_messages, theme: 'gitlab'
$('.js-broadcast-message-preview').html("#{j(render_broadcast_message(@message))}");
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
= ci_status_with_icon(build.status) = ci_status_with_icon(build.status)
%td.build-link %td.build-link
- if build.target_url - if can?(current_user, :read_build, project) && build.target_url
= link_to build.target_url do = link_to build.target_url do
%strong Build ##{build.id} %strong Build ##{build.id}
- else - else
...@@ -60,10 +60,10 @@ ...@@ -60,10 +60,10 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :read_build_artifacts, project) && build.artifacts? - if can?(current_user, :read_build, project) && build.artifacts?
= link_to build.artifacts_download_url, title: 'Download artifacts' do = link_to build.artifacts_download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, build.project) - if can?(current_user, :update_build, build.project)
- if build.active? - if build.active?
- if build.cancel_url - if build.cancel_url
= link_to build.cancel_url, method: :post, title: 'Cancel' do = link_to build.cancel_url, method: :post, title: 'Cancel' do
......
.project-issuable-filter .top-area
.controls
.pull-left.hidden-xs
- if @all_builds.running_or_pending.any?
= link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
%ul.nav-links %ul.nav-links
%li{class: ('active' if @scope.nil?)} %li{class: ('active' if @scope.nil?)}
= link_to admin_builds_path do = link_to admin_builds_path do
...@@ -20,7 +15,11 @@ ...@@ -20,7 +15,11 @@
Finished Finished
%span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id)) %span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id))
.gray-content-block .nav-controls
- if @all_builds.running_or_pending.any?
= link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
.gray-content-block.second-block
#{(@scope || 'running').capitalize} builds #{(@scope || 'running').capitalize} builds
%ul.content-list %ul.content-list
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
Explore Projects Explore Projects
.nav-controls .nav-controls
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name...', class: 'projects-list-filter form-control hidden-xs input-short', spellcheck: false = 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: 'project-filter-form-field form-control input-short projects-list-filter', spellcheck: false, id: 'project-filter-form-field'
= render 'explore/projects/dropdown' = render 'explore/projects/dropdown'
- if current_user.can_create_project? - if current_user.can_create_project?
= link_to new_project_path, class: 'btn btn-new' do = link_to new_project_path, class: 'btn btn-new' do
......
...@@ -4,17 +4,15 @@ ...@@ -4,17 +4,15 @@
- if current_user - if current_user
= auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues")
.project-issuable-filter .top-area
.controls = render 'shared/issuable/nav', type: :issues
.pull-left .nav-controls
- if current_user - if current_user
.hidden-xs.pull-left
= link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do
%i.fa.fa-rss = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
.prepend-top-default .prepend-top-default
= render 'shared/issues' = render 'shared/issues'
- page_title "Merge Requests" - page_title "Merge Requests"
- header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
.project-issuable-filter .top-area
.controls = render 'shared/issuable/nav', type: :merge_requests
.nav-controls
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
.prepend-top-default .prepend-top-default
= render 'shared/merge_requests' = render 'shared/merge_requests'
.projects-list-holder .projects-list-holder
= render 'shared/projects/list', projects: @projects, ci: true = render 'shared/projects/list', projects: @projects, ci: true
:javascript
Dashboard.init()
.pull-left
= form_tag explore_projects_filter_path, method: :get, class: 'form-inline form-tiny' do |f|
.form-group
= search_field_tag :search, params[:search], placeholder: "Filter by name", class: "form-control search-text-input", id: "projects_search", spellcheck: false
= hidden_field_tag :sort, @sort
.form-group
= button_tag 'Search', class: "btn"
.pull-right.hidden-sm.hidden-xs .pull-right.hidden-sm.hidden-xs
- if current_user - if current_user
.dropdown.inline.append-right-10 .dropdown.inline.append-right-10
......
- if projects.any? - if projects.any?
.public-projects .projects-list-holder
= render 'shared/projects/list', projects: projects = render 'shared/projects/list', projects: projects
- else - else
.nothing-here-block .nothing-here-block
......
...@@ -13,4 +13,3 @@ ...@@ -13,4 +13,3 @@
= render 'filter' = render 'filter'
= render 'projects', projects: @projects = render 'projects', projects: @projects
= paginate @projects, theme: "gitlab"
...@@ -7,5 +7,4 @@ ...@@ -7,5 +7,4 @@
= render 'explore/head' = render 'explore/head'
= render 'explore/projects/nav' = render 'explore/projects/nav'
= render 'projects', projects: @starred_projects = render 'projects', projects: @projects
= paginate @starred_projects, theme: 'gitlab'
...@@ -7,4 +7,4 @@ ...@@ -7,4 +7,4 @@
= render 'explore/head' = render 'explore/head'
= render 'explore/projects/nav' = render 'explore/projects/nav'
= render 'projects', projects: @trending_projects = render 'projects', projects: @projects
.projects-list-holder.prepend-top-default .top-area
.input-group .nav-controls
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
- if can? current_user, :create_projects, @group = 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'
%span.input-group-btn - if current_user && current_user.can_create_project?
= link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new' do = link_to new_project_path, class: 'btn btn-new' do
= icon('plus') = icon('plus')
New Project New Project
.projects-list-holder
= render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true = render 'shared/projects/list', projects: @projects, projects_limit: 20, stars: false, skip_namespace: true
...@@ -4,17 +4,15 @@ ...@@ -4,17 +4,15 @@
- if current_user - if current_user
= auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues")
.project-issuable-filter .top-area
.controls = render 'shared/issuable/nav', type: :issues
.pull-left .nav-controls
- if current_user - if current_user
.hidden-xs.pull-left
= link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do
%i.fa.fa-rss = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue"
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
.gray-content-block.second-block .gray-content-block.second-block
Only issues from Only issues from
......
- page_title "Merge Requests" - page_title "Merge Requests"
- header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group)) - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group))
.project-issuable-filter .top-area
.controls = render 'shared/issuable/nav', type: :merge_requests
.nav-controls
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request"
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
.gray-content-block.second-block .gray-content-block.second-block
Only merge requests from Only merge requests from
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
= render 'shared/event_filter' = render 'shared/event_filter'
.content_list .content_list{data: {href: events_group_path}}
= spinner = spinner
.tab-pane#projects .tab-pane#projects
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
.header-logo .header-logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do %a#logo
= brand_header_logo = brand_header_logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do
.gitlab-text-container .gitlab-text-container
%h3 GitLab %h3 GitLab
......
.search .search
= form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f|
= search_field_tag "search", nil, placeholder: 'search', class: "search-input form-control", spellcheck: false = search_field_tag "search", nil, placeholder: 'Search', class: "search-input form-control", spellcheck: false
= hidden_field_tag :group_id, @group.try(:id) = hidden_field_tag :group_id, @group.try(:id)
- if @project && @project.persisted? - if @project && @project.persisted?
= hidden_field_tag :project_id, @project.id = hidden_field_tag :project_id, @project.id
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
= render "layouts/broadcast" = render "layouts/broadcast"
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
.header-logo .header-logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do %a#logo
= brand_header_logo = brand_header_logo
= link_to root_path, class: 'home', title: 'Dashboard', id: 'js-shortcuts-home' do
.gitlab-text-container .gitlab-text-container
%h3 GitLab %h3 GitLab
......
- if current_application_settings.email_author_in_body
%div
#{link_to @note.author_name, user_url(@note.author)} wrote:
%div %div
= markdown(@note.note, pipeline: :email) = markdown(@note.note, pipeline: :email)
- if current_application_settings.email_author_in_body
%div
#{link_to @issue.author_name, user_url(@issue.author)} wrote:
-if @issue.description -if @issue.description
= markdown(@issue.description, pipeline: :email) = markdown(@issue.description, pipeline: :email)
......
- if current_application_settings.email_author_in_body
%div
#{link_to @merge_request.author_name, user_url(@merge_request.author)} wrote:
%p.details %p.details
!= merge_path_description(@merge_request, '&rarr;') != merge_path_description(@merge_request, '&rarr;')
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
= number_with_delimiter(@all_builds.finished.count(:id)) = number_with_delimiter(@all_builds.finished.count(:id))
.nav-controls .nav-controls
- if can?(current_user, :manage_builds, @project) - if can?(current_user, :update_build, @project)
- if @all_builds.running_or_pending.any? - if @all_builds.running_or_pending.any?
= link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project),
data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
......
...@@ -89,8 +89,7 @@ ...@@ -89,8 +89,7 @@
Test coverage Test coverage
%h1 #{@build.coverage}% %h1 #{@build.coverage}%
- if current_user && can?(current_user, :read_build_artifacts, @project) && @build.artifacts? - if can?(current_user, :read_build, @project) && @build.artifacts?
.build-widget.artifacts .build-widget.artifacts
%h4.title Build artifacts %h4.title Build artifacts
.center .center
...@@ -102,7 +101,7 @@ ...@@ -102,7 +101,7 @@
.build-widget .build-widget
%h4.title %h4.title
Build ##{@build.id} Build ##{@build.id}
- if current_user && can?(current_user, :manage_builds, @project) - if can?(current_user, :update_build, @project)
.pull-right .pull-right
- if @build.cancel_url - if @build.cancel_url
= link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post
......
.gray-content-block.middle-block .gray-content-block.middle-block
.pull-right .pull-right
- if can?(current_user, :manage_builds, @ci_commit.project) - if can?(current_user, :update_build, @ci_commit.project)
- if @ci_commit.builds.latest.failed.any?(&:retryable?) - if @ci_commit.builds.latest.failed.any?(&:retryable?)
= link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post = link_to "Retry failed", retry_builds_namespace_project_commit_path(@ci_commit.project.namespace, @ci_commit.project, @ci_commit.sha), class: 'btn btn-grouped btn-primary', method: :post
......
%tr.commit_status %tr.commit_status
%td.status %td.status
- if commit_status.target_url - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url
= link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do = link_to commit_status.target_url, class: "ci-status ci-#{commit_status.status}" do
= ci_icon_for_status(commit_status.status) = ci_icon_for_status(commit_status.status)
= commit_status.status = commit_status.status
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
= ci_status_with_icon(commit_status.status) = ci_status_with_icon(commit_status.status)
%td.commit_status-link %td.commit_status-link
- if commit_status.target_url - if can?(current_user, :read_commit_status, commit_status) && commit_status.target_url
= link_to commit_status.target_url do = link_to commit_status.target_url do
%strong ##{commit_status.id} %strong ##{commit_status.id}
- else - else
%strong ##{commit_status.id} %strong ##{commit_status.id}
- if commit_status.show_warning? - if commit_status.show_warning?
%i.fa.fa-warning.text-warning %i.fa.fa-warning.text-warning{data: { toggle: "tooltip" }, title: "This build is stuck, open it to know more"}
- if defined?(commit_sha) && commit_sha - if defined?(commit_sha) && commit_sha
%td %td
...@@ -66,10 +66,10 @@ ...@@ -66,10 +66,10 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :read_build_artifacts, commit_status.project) && commit_status.artifacts_download_url - if can?(current_user, :read_commit_status, commit_status) && commit_status.artifacts_download_url
= link_to commit_status.artifacts_download_url, title: 'Download artifacts' do = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, commit_status.project) - if can?(current_user, :update_commit_status, commit_status)
- if commit_status.active? - if commit_status.active?
- if commit_status.cancel_url - if commit_status.cancel_url
= link_to commit_status.cancel_url, method: :post, title: 'Cancel' do = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do
......
...@@ -130,6 +130,7 @@ ...@@ -130,6 +130,7 @@
%strong git fetch %strong git fetch
%br %br
%span.descr Faster %span.descr Faster
.form-group .form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label' = f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label'
.col-sm-10 .col-sm-10
...@@ -158,6 +159,13 @@ ...@@ -158,6 +159,13 @@
phpunit --coverage-text --colors=never (PHP) - phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\% %code ^\s*Lines:\s*\d+.\d+\%
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :public_builds do
= f.check_box :public_builds
%strong Public builds
.help-block Allow everyone to access builds for Public and Internal projects
%fieldset.features %fieldset.features
%legend %legend
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
== #{pluralize(@all_forks.size, 'fork')}: #{full_count_title} == #{pluralize(@all_forks.size, 'fork')}: #{full_count_title}
.nav-controls .nav-controls
= search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter form-control input-short', = search_field_tag :filter_projects, nil, placeholder: 'Search forks', class: 'projects-list-filter project-filter-form-field form-control input-short',
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' } spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
.dropdown .dropdown
......
...@@ -5,22 +5,19 @@ ...@@ -5,22 +5,19 @@
- if current_user - if current_user
= auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues")
.project-issuable-filter .top-area
.controls = render 'shared/issuable/nav', type: :issues
.pull-left .nav-controls
- if current_user - if current_user
.hidden-xs.pull-left
= link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do
%i.fa.fa-rss = icon('rss')
= render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project)
- if can? current_user, :create_issue, @project - if can? current_user, :create_issue, @project
= link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do
%i.fa.fa-plus = icon('plus')
New Issue New Issue
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
.issues-holder .issues-holder
= render "issues" = render "issues"
...@@ -15,11 +15,6 @@ ...@@ -15,11 +15,6 @@
opened by #{link_to_member(@project, @issue.author, size: 24)} opened by #{link_to_member(@project, @issue.author, size: 24)}
&middot; &middot;
= time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago') = time_ago_with_tooltip(@issue.created_at, placement: 'bottom', html_class: 'issue_created_ago')
- if @issue.updated_at != @issue.created_at
%span
&middot;
= icon('edit', title: 'edited')
= time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
.pull-right .pull-right
- if can?(current_user, :create_issue, @project) - if can?(current_user, :create_issue, @project)
...@@ -46,6 +41,10 @@ ...@@ -46,6 +41,10 @@
= markdown(@issue.description, cache_key: [@issue, "description"]) = markdown(@issue.description, cache_key: [@issue, "description"])
%textarea.hidden.js-task-list-field %textarea.hidden.js-task-list-field
= @issue.description = @issue.description
- if @issue.updated_at != @issue.created_at
%small
Edited
= time_ago_with_tooltip(@issue.updated_at, placement: 'bottom', html_class: 'issue_edited_ago')
.merge-requests .merge-requests
= render 'merge_requests' = render 'merge_requests'
......
...@@ -2,16 +2,19 @@ ...@@ -2,16 +2,19 @@
= render "header_title" = render "header_title"
= render 'projects/last_push' = render 'projects/last_push'
.project-issuable-filter
.controls .top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls
= render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project)
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- if merge_project - if merge_project
.pull-left.hidden-xs
= link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do
%i.fa.fa-plus = icon('plus')
New Merge Request New Merge Request
= render 'shared/issuable/filter', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests
.merge-requests-holder .merge-requests-holder
= render 'merge_requests' = render 'merge_requests'
...@@ -10,3 +10,8 @@ ...@@ -10,3 +10,8 @@
= markdown(@merge_request.description, cache_key: [@merge_request, "description"]) = markdown(@merge_request.description, cache_key: [@merge_request, "description"])
%textarea.hidden.js-task-list-field %textarea.hidden.js-task-list-field
= @merge_request.description = @merge_request.description
- if @merge_request.updated_at != @merge_request.created_at
%small
Edited
= time_ago_with_tooltip(@merge_request.updated_at, placement: 'bottom')
...@@ -8,11 +8,6 @@ ...@@ -8,11 +8,6 @@
opened by #{link_to_member(@project, @merge_request.author, size: 24)} opened by #{link_to_member(@project, @merge_request.author, size: 24)}
&middot; &middot;
= time_ago_with_tooltip(@merge_request.created_at) = time_ago_with_tooltip(@merge_request.created_at)
- if @merge_request.updated_at != @merge_request.created_at
%span
&middot;
= icon('edit', title: 'edited')
= time_ago_with_tooltip(@merge_request.updated_at, placement: 'bottom')
.issue-btn-group.pull-right .issue-btn-group.pull-right
- if can?(current_user, :update_merge_request, @merge_request) - if can?(current_user, :update_merge_request, @merge_request)
......
...@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -4,7 +4,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: namespace_project_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml" xml.link href: namespace_project_url(@project.namespace, @project, format: :atom, private_token: current_user.try(:private_token)), rel: "self", type: "application/atom+xml"
xml.link href: namespace_project_url(@project.namespace, @project), rel: "alternate", type: "text/html" xml.link href: namespace_project_url(@project.namespace, @project), rel: "alternate", type: "text/html"
xml.id namespace_project_url(@project.namespace, @project) xml.id namespace_project_url(@project.namespace, @project)
xml.updated @events[0].updated_at.xmlschema if @events[0? xml.updated @events[0].updated_at.xmlschema if @events[0]
@events.each do |event| @events.each do |event|
event_to_atom(xml, event) event_to_atom(xml, event)
......
%article.file-holder.readme-holder %article.file-holder.readme-holder
.file-title .file-title
= blob_icon readme.mode, readme.name = blob_icon readme.mode, readme.name
= link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, @path, readme.name)) do
%strong %strong
= readme.name = readme.name
.file-content.wiki .file-content.wiki
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
Secret Variables Secret Variables
%p.light %p.light
These variables will be set to environment by the runner and will be hidden in the build log. These variables will be set to environment by the runner.
%br %br
So you can use them for passwords, secret keys or whatever you want. So you can use them for passwords, secret keys or whatever you want.
%br
The value of the variable can be visible in build log if explicitly asked to do so.
%hr %hr
......
- snippet_blob = chunk_snippet(snippet_blob, @search_term)
- snippet = snippet_blob[:snippet_object]
- snippet_chunks = snippet_blob[:snippet_chunks]
.search-result-row .search-result-row
%span %span
= snippet_blob[:snippet_object].title = snippet.title
by by
= link_to user_snippets_path(snippet_blob[:snippet_object].author) do = link_to user_snippets_path(snippet.author) do
= image_tag avatar_icon(snippet_blob[:snippet_object].author_email), class: "avatar avatar-inline s16", alt: '' = image_tag avatar_icon(snippet.author_email), class: "avatar avatar-inline s16", alt: ''
= snippet_blob[:snippet_object].author_name = snippet.author_name
%span.light #{time_ago_with_tooltip(snippet_blob[:snippet_object].created_at)} %span.light #{time_ago_with_tooltip(snippet.created_at)}
%h4.snippet-title %h4.snippet-title
- snippet_path = reliable_snippet_path(snippet_blob[:snippet_object]) - snippet_path = reliable_snippet_path(snippet)
= link_to snippet_path do = link_to snippet_path do
.file-holder .file-holder
.file-title .file-title
%i.fa.fa-file %i.fa.fa-file
%strong= snippet_blob[:snippet_object].file_name %strong= snippet.file_name
- if markup?(snippet_blob[:snippet_object].file_name) - if markup?(snippet.file_name)
.file-content.wiki .file-content.wiki
- snippet_blob[:snippet_chunks].each do |snippet| - snippet_chunks.each do |chunk|
- unless snippet[:data].empty? - unless chunk[:data].empty?
= render_markup(snippet_blob[:snippet_object].file_name, snippet[:data]) = render_markup(snippet.file_name, chunk[:data])
- else - else
.file-content.code .file-content.code
.nothing-here-block Empty file .nothing-here-block Empty file
- else - else
.file-content.code.js-syntax-highlight .file-content.code.js-syntax-highlight
.line-numbers .line-numbers
- snippet_blob[:snippet_chunks].each do |snippet| - snippet_chunks.each do |chunk|
- unless snippet[:data].empty? - unless chunk[:data].empty?
- snippet[:data].lines.to_a.size.times do |index| - chunk[:data].lines.to_a.size.times do |index|
- offset = defined?(snippet[:start_line]) ? snippet[:start_line] : 1 - offset = defined?(chunk[:start_line]) ? chunk[:start_line] : 1
- i = index + offset - i = index + offset
= link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}", class: "diff-line-num" do = link_to snippet_path+"#L#{i}", id: "L#{i}", rel: "#L#{i}", class: "diff-line-num" do
%i.fa.fa-link %i.fa.fa-link
= i = i
- unless snippet == snippet_blob[:snippet_chunks].last - unless snippet == snippet_chunks.last
%a.diff-line-num %a.diff-line-num
= "." = "."
%pre.code %pre.code
%code %code
- snippet_blob[:snippet_chunks].each do |snippet| - snippet_chunks.each do |chunk|
- unless snippet[:data].empty? - unless chunk[:data].empty?
= snippet[:data] = chunk[:data]
- unless snippet == snippet_blob[:snippet_chunks].last - unless chunk == snippet_chunks.last
%a %a
= "..." = "..."
- else - else
......
...@@ -11,6 +11,6 @@ ...@@ -11,6 +11,6 @@
%li %li
If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>. If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>.
%li %li
The import will time out after 4 minutes. For big repositories, use a clone/push combination. The import will time out after 15 minutes. For repositories that take longer, use a clone/push combination.
%li %li
To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}. To migrate an SVN repository, check out #{link_to "this document", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}.
<svg width="36px" height="36px" viewBox="0 0 210 210" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="tanuki-logo"> <svg width="36" height="36" id="tanuki-logo">
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage"> <path id="tanuki-right-ear" class="tanuki-shape" fill="#e24329" d="M2 14l9.38 9v-9l-4-12.28c-.205-.632-1.176-.632-1.38 0z"/>
<g id="logo" sketch:type="MSLayerGroup" transform="translate(0.000000, 10.000000)"> <path id="tanuki-left-ear" class="tanuki-shape" fill="#e24329" d="M34 14l-9.38 9v-9l4-12.28c.205-.632 1.176-.632 1.38 0z"/>
<g id="Page-1" sketch:type="MSShapeGroup"> <path id="tanuki-nose" class="tanuki-shape" fill="#e24329" d="M18,34.38 3,14 33,14 Z"/>
<g id="Fill-1-+-Group-24"> <path id="tanuki-right-eye" class="tanuki-shape" fill="#fc6d26" d="M18,34.38 11.38,14 2,14 6,25Z"/>
<g id="Group-24"> <path id="tanuki-left-eye" class="tanuki-shape" fill="#fc6d26" d="M18,34.38 24.62,14 34,14 30,25Z"/>
<g id="Group"> <path id="tanuki-right-cheek" class="tanuki-shape" fill="#fca326" d="M2 14L.1 20.16c-.18.565 0 1.2.5 1.56l17.42 12.66z"/>
<path id="tanuki-right-ear" d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" fill="#E24329" class="tanuki-shape"></path> <path id="tanuki-left-cheek" class="tanuki-shape" fill="#fca326" d="M34 14l1.9 6.16c.18.565 0 1.2-.5 1.56L18 34.38z"/>
<path id="tanuki-right-cheek" d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" fill="#FCA326" class="tanuki-shape"></path>
<path id="tanuki-right-eye" d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" fill="#FC6D26" class="tanuki-shape"></path>
<path id="tanuki-nose" d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" fill="#E24329" class="tanuki-shape"></path>
<path id="tanuki-left-eye" d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" fill="#FC6D26" class="tanuki-shape"></path>
<path id="tanuki-left-cheek" d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" fill="#FCA326" class="tanuki-shape"></path>
<path id="tanuki-left-ear" d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" fill="#E24329" class="tanuki-shape"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg> </svg>
.issues-filters .issues-filters
.issues-state-filters .issues-details-filters.gray-content-block.second-block
%ul.nav-links
- if defined?(type) && type == :merge_requests
- page_context_word = 'merge requests'
- else
- page_context_word = 'issues'
%li{class: ("active" if params[:state] == 'opened')}
= link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do
#{state_filters_text_for(:opened, @project)}
- if defined?(type) && type == :merge_requests
%li{class: ("active" if params[:state] == 'merged')}
= link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do
#{state_filters_text_for(:merged, @project)}
%li{class: ("active" if params[:state] == 'closed')}
= link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do
#{state_filters_text_for(:closed, @project)}
- else
%li{class: ("active" if params[:state] == 'closed')}
= link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do
#{state_filters_text_for(:closed, @project)}
%li{class: ("active" if params[:state] == 'all')}
= link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do
#{state_filters_text_for(:all, @project)}
.issues-details-filters.gray-content-block
= form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do
- if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project) - if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project)
.check-all-holder .check-all-holder
......
%ul.nav-links.issues-state-filters
- if defined?(type) && type == :merge_requests
- page_context_word = 'merge requests'
- else
- page_context_word = 'issues'
%li{class: ("active" if params[:state] == 'opened')}
= link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do
#{state_filters_text_for(:opened, @project)}
- if defined?(type) && type == :merge_requests
%li{class: ("active" if params[:state] == 'merged')}
= link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do
#{state_filters_text_for(:merged, @project)}
%li{class: ("active" if params[:state] == 'closed')}
= link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do
#{state_filters_text_for(:closed, @project)}
- else
%li{class: ("active" if params[:state] == 'closed')}
= link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do
#{state_filters_text_for(:closed, @project)}
%li{class: ("active" if params[:state] == 'all')}
= link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do
#{state_filters_text_for(:all, @project)}
= form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do = form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do
.append-right-10.hidden-xs.hidden-sm = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false }
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input', spellcheck: false }
= hidden_field_tag :state, params['state'] = hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope'] = hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id'] = hidden_field_tag :assignee_id, params['assignee_id']
......
...@@ -13,12 +13,12 @@ ...@@ -13,12 +13,12 @@
= icon('angle-double-right') = icon('angle-double-right')
.issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'}
- if has_prev_issuable?(@project, issuable.id) - if has_prev_issuable?(@project, issuable.id)
= link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default' = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default prev-btn'
- else - else
%a.btn.btn-default.disabled{href: '#'} %a.btn.btn-default.disabled{href: '#'}
Prev Prev
- if has_next_issuable?(@project, issuable.id) - if has_next_issuable?(@project, issuable.id)
= link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default' = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default next-btn'
- else - else
%a.btn.btn-default.disabled{href: '#'} %a.btn.btn-default.disabled{href: '#'}
Next Next
......
...@@ -8,18 +8,23 @@ ...@@ -8,18 +8,23 @@
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true - show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
%ul.projects-list %ul.projects-list
- if projects.any?
- projects.each_with_index do |project, i| - projects.each_with_index do |project, i|
- css_class = (i >= projects_limit) ? 'hide' : nil - css_class = (i >= projects_limit) ? 'hide' : nil
= render "shared/projects/project", project: project, skip_namespace: skip_namespace, = render "shared/projects/project", project: project, skip_namespace: skip_namespace,
avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar, avatar: avatar, stars: stars, css_class: css_class, ci: ci, use_creator_avatar: use_creator_avatar,
forks: forks, show_last_commit_as_description: show_last_commit_as_description forks: forks, show_last_commit_as_description: show_last_commit_as_description
- if projects.size > projects_limit - if projects.size > projects_limit && projects.kind_of?(Array)
%li.bottom.center %li.bottom.center
.light .light
#{projects_limit} of #{pluralize(projects.count, 'project')} displayed. #{projects_limit} of #{pluralize(projects.count, 'project')} displayed.
= link_to '#', class: 'js-expand' do = link_to '#', class: 'js-expand' do
Show all Show all
= paginate projects, theme: "gitlab" if projects.respond_to? :total_pages
- else
%h3 No projects found
:javascript :javascript
new ProjectsList(); new ProjectsList();
Dashboard.init();
...@@ -31,7 +31,7 @@ module Gitlab ...@@ -31,7 +31,7 @@ module Gitlab
config.encoding = "utf-8" config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file. # Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters.push(:password, :password_confirmation, :private_token, :otp_attempt) config.filter_parameters.push(:password, :password_confirmation, :private_token, :otp_attempt, :variables)
# Enable escaping HTML in JSON. # Enable escaping HTML in JSON.
config.active_support.escape_html_entities_in_json = true config.active_support.escape_html_entities_in_json = true
...@@ -52,17 +52,11 @@ module Gitlab ...@@ -52,17 +52,11 @@ module Gitlab
config.action_view.sanitized_allowed_protocols = %w(smb) config.action_view.sanitized_allowed_protocols = %w(smb)
# Relative url support # Relative URL support
# Uncomment and customize the last line to run in a non-root path # WARNING: We recommend using an FQDN to host GitLab in a root path instead
# WARNING: We recommend creating a FQDN to host GitLab in a root path instead of this. # of using a relative URL.
# Note that following settings need to be changed for this to work. # Documentation: http://doc.gitlab.com/ce/install/relative_url.html
# 1) In your application.rb file: config.relative_url_root = "/gitlab" # Uncomment and customize the following line to run in a non-root path
# 2) In your gitlab.yml file: relative_url_root: /gitlab
# 3) In your unicorn.rb: ENV['RAILS_RELATIVE_URL_ROOT'] = "/gitlab"
# 4) In ../gitlab-shell/config.yml: gitlab_url: "http://127.0.0.1/gitlab"
# 5) In lib/support/nginx/gitlab : do not use asset gzipping, remove block starting with "location ~ ^/(assets)/"
#
# To update the path, run: sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production
# #
# config.relative_url_root = "/gitlab" # config.relative_url_root = "/gitlab"
......
...@@ -38,8 +38,12 @@ production: &base ...@@ -38,8 +38,12 @@ production: &base
# Otherwise, ssh host will be set to the `host:` value above # Otherwise, ssh host will be set to the `host:` value above
# ssh_host: ssh.host_example.com # ssh_host: ssh.host_example.com
# WARNING: See config/application.rb under "Relative url support" for the list of # Relative URL support
# other files that need to be changed for relative url support # WARNING: We recommend using an FQDN to host GitLab in a root path instead
# of using a relative URL.
# Documentation: http://doc.gitlab.com/ce/install/relative_url.html
# Uncomment and customize the following line to run in a non-root path
#
# relative_url_root: /gitlab # relative_url_root: /gitlab
# Uncomment and customize if you can't use the default user to run GitLab (default: 'git') # Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
......
...@@ -12,7 +12,7 @@ if Rails.env.production? ...@@ -12,7 +12,7 @@ if Rails.env.production?
ActionMailer::Base.smtp_settings = { ActionMailer::Base.smtp_settings = {
address: "email.server.com", address: "email.server.com",
port: 456, port: 465,
user_name: "smtp", user_name: "smtp",
password: "123456", password: "123456",
domain: "gitlab.company.com", domain: "gitlab.company.com",
......
...@@ -227,7 +227,10 @@ Rails.application.routes.draw do ...@@ -227,7 +227,10 @@ Rails.application.routes.draw do
get :test get :test
end end
resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] do
post :preview, on: :collection
end
resource :logs, only: [:show] resource :logs, only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show]
...@@ -349,6 +352,7 @@ Rails.application.routes.draw do ...@@ -349,6 +352,7 @@ Rails.application.routes.draw do
get :issues get :issues
get :merge_requests get :merge_requests
get :projects get :projects
get :events
end end
scope module: :groups do scope module: :groups do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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