Commit 4c7da578 authored by Keith Pitt's avatar Keith Pitt

Merge branch 'master' into buildbox-service

Conflicts:
	app/models/project.rb
parents 76594d47 928178de
...@@ -12,7 +12,14 @@ v 7.4.0 ...@@ -12,7 +12,14 @@ v 7.4.0
- API: Add support for forking a project via the API (Bernhard Kaindl) - API: Add support for forking a project via the API (Bernhard Kaindl)
- API: filter project issues by milestone (Julien Bianchi) - API: filter project issues by milestone (Julien Bianchi)
- Fail harder in the backup script - Fail harder in the backup script
- Changes to Slack service structure, only webhook url needed
- Zen mode for wiki and milestones (Robert Schilling) - Zen mode for wiki and milestones (Robert Schilling)
- Move Emoji parsing to html-pipeline-gitlab (Robert Schilling)
- Font Awesome 4.2 integration (Sullivan Senechal)
- Add Pushover service integration (Sullivan Senechal)
- Add select field type for services options (Sullivan Senechal)
- Add cross-project references to the Markdown parser (Vinnie Okada)
- Add task lists to issue and merge request descriptions (Vinnie Okada)
v 7.3.2 v 7.3.2
- Fix creating new file via web editor - Fix creating new file via web editor
......
...@@ -10,7 +10,7 @@ By submitting code as an individual you agree to the [individual contributor lic ...@@ -10,7 +10,7 @@ By submitting code as an individual you agree to the [individual contributor lic
## Security vulnerability disclosure ## Security vulnerability disclosure
Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://www.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities. Please report suspected security vulnerabilities in private to support@gitlab.com, also see the [disclosure section on the GitLab.com website](http://about.gitlab.com/disclosure/). Please do NOT create publicly viewable issues for suspected security vulnerabilities.
## Closing policy for issues and merge requests ## Closing policy for issues and merge requests
...@@ -22,7 +22,7 @@ Issues and merge requests should be in English and contain appropriate language ...@@ -22,7 +22,7 @@ Issues and merge requests should be in English and contain appropriate language
## Issue tracker ## Issue tracker
To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://www.gitlab.com/subscription/) and [consulting services](http://www.gitlab.com/consultancy/) are available from [GitLab.com](http://www.gitlab.com/). To get support for your particular problem please use the channels as detailed in the [getting help section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#getting-help). Professional [support subscriptions](http://about.gitlab.com/subscription/) and [consulting services](http://about.gitlab.com/consultancy/) are available from [GitLab.com](http://about.gitlab.com/).
The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. When submitting an issue please conform to the issue submission guidelines listed below. Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue. The [issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues) is only for obvious errors in the latest [stable or development release of GitLab](MAINTENANCE.md). If something is wrong but it is not a regression compared to older versions of GitLab please do not open an issue but a feature request. When submitting an issue please conform to the issue submission guidelines listed below. Not all issues will be addressed and your issue is more likely to be addressed if you submit a merge request which partially or fully addresses the issue.
......
...@@ -31,7 +31,7 @@ gem 'omniauth-shibboleth' ...@@ -31,7 +31,7 @@ gem 'omniauth-shibboleth'
# 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", '7.0.0.rc8' gem "gitlab_git", '7.0.0.rc9'
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
...@@ -89,7 +89,7 @@ gem "github-markup" ...@@ -89,7 +89,7 @@ gem "github-markup"
gem 'redcarpet', '~> 3.1.2' gem 'redcarpet', '~> 3.1.2'
gem 'RedCloth' gem 'RedCloth'
gem 'rdoc', '~>3.6' gem 'rdoc', '~>3.6'
gem 'org-ruby' gem 'org-ruby', '= 0.9.9'
gem 'creole', '~>0.3.6' gem 'creole', '~>0.3.6'
gem 'wikicloth', '=0.8.1' gem 'wikicloth', '=0.8.1'
gem 'asciidoctor', '= 0.1.4' gem 'asciidoctor', '= 0.1.4'
...@@ -180,7 +180,7 @@ gem "jquery-ui-rails" ...@@ -180,7 +180,7 @@ gem "jquery-ui-rails"
gem "jquery-scrollto-rails" gem "jquery-scrollto-rails"
gem "raphael-rails", "~> 2.1.2" gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 3.0' gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2' gem "font-awesome-rails", '~> 4.2'
gem "gitlab_emoji", "~> 0.0.1.1" gem "gitlab_emoji", "~> 0.0.1.1"
gem "gon", '~> 5.0.0' gem "gon", '~> 5.0.0'
gem 'nprogress-rails' gem 'nprogress-rails'
......
...@@ -152,7 +152,7 @@ GEM ...@@ -152,7 +152,7 @@ GEM
net-ssh (>= 2.1.3) net-ssh (>= 2.1.3)
fog-json (1.0.0) fog-json (1.0.0)
multi_json (~> 1.0) multi_json (~> 1.0)
font-awesome-rails (3.2.1.3) font-awesome-rails (4.2.0.0)
railties (>= 3.2, < 5.0) railties (>= 3.2, < 5.0)
foreman (0.63.0) foreman (0.63.0)
dotenv (>= 0.7) dotenv (>= 0.7)
...@@ -179,7 +179,7 @@ GEM ...@@ -179,7 +179,7 @@ GEM
mime-types (~> 1.19) mime-types (~> 1.19)
gitlab_emoji (0.0.1.1) gitlab_emoji (0.0.1.1)
emoji (~> 1.0.1) emoji (~> 1.0.1)
gitlab_git (7.0.0.rc8) gitlab_git (7.0.0.rc9)
activesupport (~> 4.0) activesupport (~> 4.0)
charlock_holmes (~> 0.6) charlock_holmes (~> 0.6)
gitlab-linguist (~> 3.0) gitlab-linguist (~> 3.0)
...@@ -332,7 +332,7 @@ GEM ...@@ -332,7 +332,7 @@ GEM
omniauth-twitter (1.0.1) omniauth-twitter (1.0.1)
multi_json (~> 1.3) multi_json (~> 1.3)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.0)
org-ruby (0.9.8) org-ruby (0.9.9)
rubypants (~> 0.2) rubypants (~> 0.2)
orm_adapter (0.5.0) orm_adapter (0.5.0)
pg (0.15.1) pg (0.15.1)
...@@ -614,7 +614,7 @@ DEPENDENCIES ...@@ -614,7 +614,7 @@ DEPENDENCIES
factory_girl_rails factory_girl_rails
ffaker ffaker
fog (~> 1.14) fog (~> 1.14)
font-awesome-rails (~> 3.2) font-awesome-rails (~> 4.2)
foreman foreman
gemnasium-gitlab-service (~> 0.2) gemnasium-gitlab-service (~> 0.2)
github-markup github-markup
...@@ -622,7 +622,7 @@ DEPENDENCIES ...@@ -622,7 +622,7 @@ DEPENDENCIES
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 3.0.0) gitlab-linguist (~> 3.0.0)
gitlab_emoji (~> 0.0.1.1) gitlab_emoji (~> 0.0.1.1)
gitlab_git (= 7.0.0.rc8) gitlab_git (= 7.0.0.rc9)
gitlab_meta (= 7.0) gitlab_meta (= 7.0)
gitlab_omniauth-ldap (= 1.1.0) gitlab_omniauth-ldap (= 1.1.0)
gollum-lib (~> 3.0.0) gollum-lib (~> 3.0.0)
...@@ -655,7 +655,7 @@ DEPENDENCIES ...@@ -655,7 +655,7 @@ DEPENDENCIES
omniauth-google-oauth2 omniauth-google-oauth2
omniauth-shibboleth omniauth-shibboleth
omniauth-twitter omniauth-twitter
org-ruby org-ruby (= 0.9.9)
pg pg
poltergeist (~> 1.5.1) poltergeist (~> 1.5.1)
pry pry
......
...@@ -18,7 +18,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -18,7 +18,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
- Responds to merge requests the issue team mentions them in and monitors for new merge requests - Responds to merge requests the issue team mentions them in and monitors for new merge requests
- Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.) - Provides feedback to the merge request submitter to improve the merge request (style, tests, etc.)
- Mark merge requests 'ready-for-merge' when they meet the contribution guidelines - Mark merge requests 'ready-for-merge' when they meet the contribution guidelines
- Mention developer(s) based on the [list of members and their specialities](https://www.gitlab.com/core-team/) - Mention developer(s) based on the [list of members and their specialities](https://about.gitlab.com/core-team/)
- Closes merge requests with no feedback from the reporter for two weeks - Closes merge requests with no feedback from the reporter for two weeks
## Priorities of the issue team ## Priorities of the issue team
...@@ -30,7 +30,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co ...@@ -30,7 +30,7 @@ Below we describe the contributing process to GitLab for two reasons. So that co
## Mentioning people ## Mentioning people
The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](https://www.gitlab.com/core-team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person. The most important thing is making sure valid issues receive feedback from the development team. Therefore the priority is mentioning developers that can help on those issue. Please select someone with relevant experience from [GitLab core team](https://about.gitlab.com/core-team/). If there is nobody mentioned with that expertise look in the commit history for the affected files to find someone. Avoid mentioning the lead developer, this is the person that is least likely to give a timely response. If the involvement of the lead developer is needed the other core team members will mention this person.
## Workflow labels ## Workflow labels
...@@ -79,7 +79,7 @@ Thanks for the issue report but we only support issues for the latest stable ver ...@@ -79,7 +79,7 @@ Thanks for the issue report but we only support issues for the latest stable ver
### Support requests and configuration questions ### Support requests and configuration questions
Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the #gitlab IRC channel on Freenode or the http://www.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information. Thanks for your interest in GitLab. We don't use the issue tracker for support requests and configuration questions. Please use the \[support forum\]\(https://groups.google.com/forum/#!forum/gitlabhq), \[Stack Overflow\]\(http://stackoverflow.com/questions/tagged/gitlab), the #gitlab IRC channel on Freenode or the http://about.gitlab.com paid services for this purpose. Have a look at the \[contribution guidelines\]\(https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) for more information.
### Code format ### Code format
......
...@@ -172,8 +172,8 @@ $ -> ...@@ -172,8 +172,8 @@ $ ->
# Show/hide comments on diff # Show/hide comments on diff
$("body").on "click", ".js-toggle-diff-comments", (e) -> $("body").on "click", ".js-toggle-diff-comments", (e) ->
$(@).find('i'). $(@).find('i').
toggleClass('icon-chevron-down'). toggleClass('fa fa-chevron-down').
toggleClass('icon-chevron-up') toggleClass('fa fa-chevron-up')
$(@).closest(".diff-file").find(".notes_holder").toggle() $(@).closest(".diff-file").find(".notes_holder").toggle()
e.preventDefault() e.preventDefault()
......
...@@ -8,7 +8,7 @@ $ -> ...@@ -8,7 +8,7 @@ $ ->
# #
$("body").on "click", ".js-toggle-button", (e) -> $("body").on "click", ".js-toggle-button", (e) ->
$(@).find('i'). $(@).find('i').
toggleClass('icon-chevron-down'). toggleClass('fa fa-chevron-down').
toggleClass('icon-chevron-up') toggleClass('fa fa-chevron-up')
$(@).closest(".js-toggle-container").find(".js-toggle-content").toggle() $(@).closest(".js-toggle-container").find(".js-toggle-content").toggle()
e.preventDefault() e.preventDefault()
...@@ -6,4 +6,28 @@ class Issue ...@@ -6,4 +6,28 @@ class Issue
$(".issue-box .inline-update").on "change", "#issue_assignee_id", -> $(".issue-box .inline-update").on "change", "#issue_assignee_id", ->
$(this).submit() $(this).submit()
if $("a.btn-close").length
$("li.task-list-item input:checkbox").prop("disabled", false)
$(".task-list-item input:checkbox").on "click", ->
is_checked = $(this).prop("checked")
if $(this).is(":checked")
state_event = "task_check"
else
state_event = "task_uncheck"
mr_url = $("form.edit-issue").first().attr("action")
mr_num = mr_url.match(/\d+$/)
task_num = 0
$("li.task-list-item input:checkbox").each( (index, e) =>
if e == this
task_num = index + 1
)
$.ajax
type: "PATCH"
url: mr_url
data: "issue[state_event]=" + state_event +
"&issue[task_num]=" + task_num
@Issue = Issue @Issue = Issue
...@@ -7,8 +7,8 @@ $(document).ready -> ...@@ -7,8 +7,8 @@ $(document).ready ->
divHover = "<div class=\"div-dropzone-hover\"></div>" divHover = "<div class=\"div-dropzone-hover\"></div>"
divSpinner = "<div class=\"div-dropzone-spinner\"></div>" divSpinner = "<div class=\"div-dropzone-spinner\"></div>"
divAlert = "<div class=\"" + alertClass + "\"></div>" divAlert = "<div class=\"" + alertClass + "\"></div>"
iconPicture = "<i class=\"icon-picture div-dropzone-icon\"></i>" iconPicture = "<i class=\"fa fa-picture-o div-dropzone-icon\"></i>"
iconSpinner = "<i class=\"icon-spinner icon-spin div-dropzone-icon\"></i>" iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>"
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>" btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_image_path_upload = window.project_image_path_upload or null project_image_path_upload = window.project_image_path_upload or null
......
...@@ -15,8 +15,10 @@ class MergeRequest ...@@ -15,8 +15,10 @@ class MergeRequest
modal = $('#modal_merge_info').modal(show: false) modal = $('#modal_merge_info').modal(show: false)
disableButtonIfEmptyField '#merge_commit_message', '.accept_merge_request' disableButtonIfEmptyField '#commit_message', '.accept_merge_request'
if $("a.close-mr-link").length
$("li.task-list-item input:checkbox").prop("disabled", false)
# Local jQuery finder # Local jQuery finder
$: (selector) -> $: (selector) ->
...@@ -72,6 +74,27 @@ class MergeRequest ...@@ -72,6 +74,27 @@ class MergeRequest
this.$('.remove_source_branch_in_progress').hide() this.$('.remove_source_branch_in_progress').hide()
this.$('.remove_source_branch_widget.failed').show() this.$('.remove_source_branch_widget.failed').show()
this.$(".task-list-item input:checkbox").on "click", ->
is_checked = $(this).prop("checked")
if $(this).is(":checked")
state_event = "task_check"
else
state_event = "task_uncheck"
mr_url = $("form.edit-merge_request").first().attr("action")
mr_num = mr_url.match(/\d+$/)
task_num = 0
$("li.task-list-item input:checkbox").each( (index, e) =>
if e == this
task_num = index + 1
)
$.ajax
type: "PATCH"
url: mr_url
data: "merge_request[state_event]=" + state_event +
"&merge_request[task_num]=" + task_num
activateTab: (action) -> activateTab: (action) ->
this.$('.merge-request-tabs li').removeClass 'active' this.$('.merge-request-tabs li').removeClass 'active'
this.$('.tab-content').hide() this.$('.tab-content').hide()
...@@ -96,14 +119,6 @@ class MergeRequest ...@@ -96,14 +119,6 @@ class MergeRequest
else else
$('.ci_widget.ci-error').show() $('.ci_widget.ci-error').show()
switch state
when "success"
$('.mr-state-widget').addClass("panel-success")
when "failed"
$('.mr-state-widget').addClass("panel-danger")
when "running", "pending"
$('.mr-state-widget').addClass("panel-warning")
showCiCoverage: (coverage) -> showCiCoverage: (coverage) ->
cov_html = $('<span>') cov_html = $('<span>')
cov_html.addClass('ci-coverage') cov_html.addClass('ci-coverage')
......
...@@ -356,3 +356,6 @@ table { ...@@ -356,3 +356,6 @@ table {
font-size: 42px; font-size: 42px;
} }
.task-status {
margin-left: 10px;
}
...@@ -122,3 +122,7 @@ ul.bordered-list { ...@@ -122,3 +122,7 @@ ul.bordered-list {
} }
} }
} }
li.task-list-item {
list-style-type: none;
}
...@@ -124,7 +124,7 @@ $list-group-active-bg: $bg_primary; ...@@ -124,7 +124,7 @@ $list-group-active-bg: $bg_primary;
color: #888; color: #888;
text-shadow: 0 1px 1px #fff; text-shadow: 0 1px 1px #fff;
} }
i[class^="icon-"] { i[class~="fa"] {
line-height: 14px; line-height: 14px;
} }
} }
......
...@@ -104,7 +104,44 @@ ...@@ -104,7 +104,44 @@
} }
.mr-state-widget { .mr-state-widget {
.panel-body { background: #f9f9f9;
margin-bottom: 20px;
@include box-shadow(0 1px 1px rgba(0, 0, 0, 0.09));
.ci_widget {
padding: 10px 15px;
font-size: 15px;
border-bottom: 1px dashed #AAA;
&.ci-success {
color: $bg_success;
border-color: $border_success;
}
&.ci-pending {
color: #548;
border-color: #548;
}
&.ci-running {
color: $bg_warning;
border-color: $border_warning;
}
&.ci-failed {
color: $bg_danger;
border-color: $border_danger;
}
&.ci-error {
color: $bg_danger;
border-color: $border_danger;
}
}
.mr-widget-body {
padding: 10px 15px;
h4 { h4 {
margin-top: 0px; margin-top: 0px;
} }
...@@ -114,6 +151,11 @@ ...@@ -114,6 +151,11 @@
} }
} }
.mr-widget-footer {
padding: 10px 15px;
border-top: 1px solid #EEE;
}
.ci-coverage { .ci-coverage {
float: right; float: right;
} }
......
...@@ -8,8 +8,6 @@ ...@@ -8,8 +8,6 @@
ul { ul {
padding: 0; padding: 0;
margin: auto; margin: auto;
height: 40px;
overflow: hidden;
.count { .count {
font-weight: normal; font-weight: normal;
display: inline-block; display: inline-block;
...@@ -37,53 +35,28 @@ ...@@ -37,53 +35,28 @@
a { a {
color: $link_color; color: $link_color;
font-weight: bold; font-weight: bold;
&:after { border-bottom: 3px solid $link_color;
content: '';
display: block;
position: relative;
bottom: -1px;
border-color: $link_color;
border-style: solid;
border-width: 2px;
}
} }
} }
&:hover { &:hover {
a { a {
color: $link_hover_color; color: $link_hover_color;
&:after { border-bottom: 3px solid $link_hover_color;
content: '';
display: block;
position: relative;
bottom: -1px;
border-color: $link_hover_color;
border-style: solid;
border-width: 2px;
}
}
}
&.home {
a {
i {
font-size: 20px;
position: relative;
top: 4px;
}
} }
} }
} }
a { a {
display: block; display: block;
text-align: center; text-align: center;
font-weight: 500; font-weight: bold;
height: 38px; height: 42px;
line-height: 34px; line-height: 39px;
color: #777; color: #777;
text-shadow: 0 1px 1px white; text-shadow: 0 1px 1px white;
text-decoration: none; text-decoration: none;
padding-top: 2px; overflow: hidden;
margin-bottom: -1px;
} }
} }
......
...@@ -119,8 +119,7 @@ ul.notes { ...@@ -119,8 +119,7 @@ ul.notes {
display: none; display: none;
float: right; float: right;
[class^="icon-"], [class~="fa"] {
[class*="icon-"] {
font-size: 16px; font-size: 16px;
line-height: 16px; line-height: 16px;
vertical-align: middle; vertical-align: middle;
......
...@@ -13,7 +13,7 @@ class ApplicationController < ActionController::Base ...@@ -13,7 +13,7 @@ class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller? before_filter :configure_permitted_parameters, if: :devise_controller?
before_filter :require_email, unless: :devise_controller? before_filter :require_email, unless: :devise_controller?
protect_from_forgery protect_from_forgery with: :exception
helper_method :abilities, :can? helper_method :abilities, :can?
...@@ -62,7 +62,7 @@ class ApplicationController < ActionController::Base ...@@ -62,7 +62,7 @@ class ApplicationController < ActionController::Base
end end
end end
def after_sign_in_path_for resource def after_sign_in_path_for(resource)
if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked? if resource.is_a?(User) && resource.respond_to?(:blocked?) && resource.blocked?
sign_out resource sign_out resource
flash[:alert] = "Your account is blocked. Retry when an admin has unblocked it." flash[:alert] = "Your account is blocked. Retry when an admin has unblocked it."
......
class ConfirmationsController < Devise::ConfirmationsController
protected
def after_confirmation_path_for(resource_name, resource)
if signed_in?(resource_name)
signed_in_root_path(resource)
else
sign_in(resource)
if signed_in?(resource_name)
signed_in_root_path(resource)
else
new_session_path(resource_name)
end
end
end
end
...@@ -17,7 +17,7 @@ class Projects::CommitsController < Projects::ApplicationController ...@@ -17,7 +17,7 @@ class Projects::CommitsController < Projects::ApplicationController
group(:commit_id).count group(:commit_id).count
respond_to do |format| respond_to do |format|
format.html # index.html.erb format.html
format.json { pager_json("projects/commits/_commits", @commits.size) } format.json { pager_json("projects/commits/_commits", @commits.size) }
format.atom { render layout: false } format.atom { render layout: false }
end end
......
...@@ -152,7 +152,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -152,7 +152,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue_params def issue_params
params.require(:issue).permit( params.require(:issue).permit(
:title, :assignee_id, :position, :description, :title, :assignee_id, :position, :description,
:milestone_id, :state_event, label_ids: [] :milestone_id, :state_event, :task_num, label_ids: []
) )
end end
end end
...@@ -122,7 +122,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -122,7 +122,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if @merge_request.open? && @merge_request.can_be_merged? if @merge_request.open? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch] @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user, params[:merge_commit_message]) @merge_request.automerge!(current_user, params[:commit_message])
@status = true @status = true
else else
@status = false @status = false
...@@ -250,7 +250,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -250,7 +250,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
params.require(:merge_request).permit( params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch, :title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id, :target_project_id, :target_branch, :milestone_id,
:state_event, :description, label_ids: [] :state_event, :description, :task_num, label_ids: []
) )
end end
end end
...@@ -40,7 +40,8 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -40,7 +40,8 @@ class Projects::ServicesController < Projects::ApplicationController
def service_params def service_params
params.require(:service).permit( params.require(:service).permit(
:title, :token, :type, :active, :api_key, :subdomain, :title, :token, :type, :active, :api_key, :subdomain,
:room, :recipients, :project_url :room, :recipients, :project_url, :webhook,
:user_key, :device, :priority, :sound
) )
end end
end end
...@@ -15,11 +15,11 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -15,11 +15,11 @@ class RegistrationsController < Devise::RegistrationsController
super super
end end
def after_sign_up_path_for resource def after_sign_up_path_for(resource)
new_user_session_path new_user_session_path
end end
def after_inactive_sign_up_path_for resource def after_inactive_sign_up_path_for(resource)
new_user_session_path new_user_session_path
end end
......
...@@ -14,7 +14,7 @@ class SnippetsController < ApplicationController ...@@ -14,7 +14,7 @@ class SnippetsController < ApplicationController
layout 'navless' layout 'navless'
def index def index
@snippets = Snippet.are_public.fresh.non_expired.page(params[:page]).per(20) @snippets = Snippet.are_internal.fresh.non_expired.page(params[:page]).per(20)
end end
def user_index def user_index
...@@ -26,15 +26,15 @@ class SnippetsController < ApplicationController ...@@ -26,15 +26,15 @@ class SnippetsController < ApplicationController
if @user == current_user if @user == current_user
@snippets = case params[:scope] @snippets = case params[:scope]
when 'are_public' then when 'are_internal' then
@snippets.are_public @snippets.are_internal
when 'are_private' then when 'are_private' then
@snippets.are_private @snippets.are_private
else else
@snippets @snippets
end end
else else
@snippets = @snippets.are_public @snippets = @snippets.are_internal
end end
@snippets = @snippets.page(params[:page]).per(20) @snippets = @snippets.page(params[:page]).per(20)
......
# Finders # Finders
This type of classes responsible for collectiong items based on different conditions. This type of classes responsible for collection items based on different conditions.
To prevent lookup methods in models like this: To prevent lookup methods in models like this:
```ruby ```ruby
class Project class Project
...@@ -13,10 +13,10 @@ end ...@@ -13,10 +13,10 @@ end
issues = project.issues_for_user_filtered_by(user, params) issues = project.issues_for_user_filtered_by(user, params)
``` ```
Better use this: Better use this:
```ruby ```ruby
issues = IssuesFinder.new.execute(project, user, filter) issues = IssuesFinder.new.execute(project, user, filter)
``` ```
It will help keep models thiner It will help keep models thiner.
...@@ -229,7 +229,7 @@ module ApplicationHelper ...@@ -229,7 +229,7 @@ module ApplicationHelper
css_class << " hide" unless visible css_class << " hide" unless visible
content_tag :div, class: css_class do content_tag :div, class: css_class do
content_tag(:i, nil, class: 'icon-spinner icon-spin') + text content_tag(:i, nil, class: 'fa fa-spinner fa-spin') + text
end end
end end
...@@ -259,4 +259,16 @@ module ApplicationHelper ...@@ -259,4 +259,16 @@ module ApplicationHelper
super super
end end
def escaped_autolink(text)
auto_link ERB::Util.html_escape(text), link: :urls
end
def promo_host
'about.gitlab.com'
end
def promo_url
'https://' + promo_host
end
end end
...@@ -19,7 +19,7 @@ module EventsHelper ...@@ -19,7 +19,7 @@ module EventsHelper
[event.action_name, target].join(" ") [event.action_name, target].join(" ")
end end
def event_filter_link key, tooltip def event_filter_link(key, tooltip)
key = key.to_s key = key.to_s
inactive = if @event_filter.active? key inactive = if @event_filter.active? key
nil nil
...@@ -36,10 +36,10 @@ module EventsHelper ...@@ -36,10 +36,10 @@ module EventsHelper
def icon_for_event def icon_for_event
{ {
EventFilter.push => "icon-upload-alt", EventFilter.push => 'fa fa-upload',
EventFilter.merged => "icon-check", EventFilter.merged => 'fa fa-check-square-o',
EventFilter.comments => "icon-comments", EventFilter.comments => 'fa fa-comments',
EventFilter.team => "icon-user", EventFilter.team => 'fa fa-user',
} }
end end
......
module IconsHelper module IconsHelper
def boolean_to_icon(value) def boolean_to_icon(value)
if value.to_s == "true" if value.to_s == "true"
content_tag :i, nil, class: 'icon-circle cgreen' content_tag :i, nil, class: 'fa fa-circle cgreen'
else else
content_tag :i, nil, class: 'icon-off clgray' content_tag :i, nil, class: 'fa fa-power-off clgray'
end end
end end
def public_icon def public_icon
content_tag :i, nil, class: 'icon-globe' content_tag :i, nil, class: 'fa fa-globe'
end end
def internal_icon def internal_icon
content_tag :i, nil, class: 'icon-shield' content_tag :i, nil, class: 'fa fa-shield'
end end
def private_icon def private_icon
content_tag :i, nil, class: 'icon-lock' content_tag :i, nil, class: 'fa fa-lock'
end end
end end
module IssuesHelper module IssuesHelper
def issue_css_classes issue def issue_css_classes(issue)
classes = "issue" classes = "issue"
classes << " closed" if issue.closed? classes << " closed" if issue.closed?
classes << " today" if issue.today? classes << " today" if issue.today?
...@@ -84,7 +84,7 @@ module IssuesHelper ...@@ -84,7 +84,7 @@ module IssuesHelper
'id', 'name', object.assignee_id) 'id', 'name', object.assignee_id)
end end
def milestone_options object def milestone_options(object)
options_from_collection_for_select(object.project.milestones.active, options_from_collection_for_select(object.project.milestones.active,
'id', 'title', object.milestone_id) 'id', 'title', object.milestone_id)
end end
......
...@@ -19,19 +19,18 @@ module MergeRequestsHelper ...@@ -19,19 +19,18 @@ module MergeRequestsHelper
source_project_id: event.project.id, source_project_id: event.project.id,
target_project_id: target_project.id, target_project_id: target_project.id,
source_branch: event.branch_name, source_branch: event.branch_name,
target_branch: target_project.repository.root_ref, target_branch: target_project.repository.root_ref
title: event.branch_name.titleize.humanize
} }
end end
def mr_css_classes mr def mr_css_classes(mr)
classes = "merge-request" classes = "merge-request"
classes << " closed" if mr.closed? classes << " closed" if mr.closed?
classes << " merged" if mr.merged? classes << " merged" if mr.merged?
classes classes
end end
def ci_build_details_path merge_request def ci_build_details_path(merge_request)
merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha) merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha)
end end
......
...@@ -69,7 +69,7 @@ module NotesHelper ...@@ -69,7 +69,7 @@ module NotesHelper
button_tag class: 'btn reply-btn js-discussion-reply-button', button_tag class: 'btn reply-btn js-discussion-reply-button',
data: data, title: 'Add a reply' do data: data, title: 'Add a reply' do
link_text = content_tag(:i, nil, class: 'icon-comment') link_text = content_tag(:i, nil, class: 'fa fa-comment')
link_text << ' Reply' link_text << ' Reply'
end end
end end
......
module NotificationsHelper module NotificationsHelper
def notification_icon(notification) def notification_icon(notification)
if notification.disabled? if notification.disabled?
content_tag :i, nil, class: 'icon-volume-off ns-mute' content_tag :i, nil, class: 'fa fa-volume-off ns-mute'
elsif notification.participating? elsif notification.participating?
content_tag :i, nil, class: 'icon-volume-down ns-part' content_tag :i, nil, class: 'fa fa-volume-down ns-part'
elsif notification.watch? elsif notification.watch?
content_tag :i, nil, class: 'icon-volume-up ns-watch' content_tag :i, nil, class: 'fa fa-volume-up ns-watch'
else else
content_tag :i, nil, class: 'icon-circle-blank ns-default' content_tag :i, nil, class: 'fa fa-circle-o ns-default'
end end
end end
end end
module ProfileHelper module ProfileHelper
def oauth_active_class provider def oauth_active_class(provider)
if current_user.provider == provider.to_s if current_user.provider == provider.to_s
'active' 'active'
end end
......
...@@ -3,7 +3,7 @@ module ProjectsHelper ...@@ -3,7 +3,7 @@ module ProjectsHelper
"You are going to remove #{user.name} from #{project.name} project team. Are you sure?" "You are going to remove #{user.name} from #{project.name} project team. Are you sure?"
end end
def link_to_project project def link_to_project(project)
link_to project do link_to project do
title = content_tag(:span, project.name, class: 'project-name') title = content_tag(:span, project.name, class: 'project-name')
...@@ -39,7 +39,7 @@ module ProjectsHelper ...@@ -39,7 +39,7 @@ module ProjectsHelper
end end
end end
def project_title project def project_title(project)
if project.group if project.group
content_tag :span do content_tag :span do
link_to(simple_sanitize(project.group.name), group_path(project.group)) + " / " + project.name link_to(simple_sanitize(project.group.name), group_path(project.group)) + " / " + project.name
...@@ -128,12 +128,12 @@ module ProjectsHelper ...@@ -128,12 +128,12 @@ module ProjectsHelper
toggle_html = content_tag('span', class: 'toggle') do toggle_html = content_tag('span', class: 'toggle') do
toggle_text = if starred toggle_text = if starred
'Unstar' ' Unstar'
else else
'Star' ' Star'
end end
content_tag('i', ' ', class: 'icon-star') + toggle_text content_tag('i', ' ', class: 'fa fa-star') + toggle_text
end end
count_html = content_tag('span', class: 'count') do count_html = content_tag('span', class: 'count') do
...@@ -157,7 +157,7 @@ module ProjectsHelper ...@@ -157,7 +157,7 @@ module ProjectsHelper
end end
def link_to_toggle_fork def link_to_toggle_fork
out = content_tag(:i, '', class: 'icon-code-fork') out = content_tag(:i, '', class: 'fa fa-code-fork')
out << ' Fork' out << ' Fork'
out << content_tag(:span, class: 'count') do out << content_tag(:span, class: 'count') do
@project.forks_count.to_s @project.forks_count.to_s
......
...@@ -89,7 +89,7 @@ module TabHelper ...@@ -89,7 +89,7 @@ module TabHelper
end end
# Use nav_tab for save controller/action but different params # Use nav_tab for save controller/action but different params
def nav_tab key, value, &block def nav_tab(key, value, &block)
o = {} o = {}
o[:class] = "" o[:class] = ""
......
module TagsHelper module TagsHelper
def tag_path tag def tag_path(tag)
"/tags/#{tag}" "/tags/#{tag}"
end end
def tag_list project def tag_list(project)
html = '' html = ''
project.tag_list.each do |tag| project.tag_list.each do |tag|
html += link_to tag, tag_path(tag) html += link_to tag, tag_path(tag)
......
...@@ -36,9 +36,9 @@ module TreeHelper ...@@ -36,9 +36,9 @@ module TreeHelper
# type - String type of the tree item; either 'folder' or 'file' # type - String type of the tree item; either 'folder' or 'file'
def tree_icon(type) def tree_icon(type)
icon_class = if type == 'folder' icon_class = if type == 'folder'
'icon-folder-close' 'fa fa-folder'
else else
'icon-file-alt' 'fa fa-file-o'
end end
content_tag :i, nil, class: icon_class content_tag :i, nil, class: icon_class
...@@ -80,7 +80,7 @@ module TreeHelper ...@@ -80,7 +80,7 @@ module TreeHelper
end end
end end
def up_dir_path tree def up_dir_path(tree)
file = File.join(@path, "..") file = File.join(@path, "..")
tree_join(@ref, file) tree_join(@ref, file)
end end
...@@ -90,7 +90,7 @@ module TreeHelper ...@@ -90,7 +90,7 @@ module TreeHelper
end end
def editing_preview_title(filename) def editing_preview_title(filename)
if gitlab_markdown?(filename) || markup?(filename) if Gitlab::MarkdownHelper.previewable?(filename)
'Preview' 'Preview'
else else
'Diff' 'Diff'
......
...@@ -184,7 +184,7 @@ class Ability ...@@ -184,7 +184,7 @@ class Ability
] ]
end end
def group_abilities user, group def group_abilities(user, group)
rules = [] rules = []
if user.admin? || group.users.include?(user) || ProjectsFinder.new.execute(user, group: group).any? if user.admin? || group.users.include?(user) || ProjectsFinder.new.execute(user, group: group).any?
...@@ -209,7 +209,7 @@ class Ability ...@@ -209,7 +209,7 @@ class Ability
rules.flatten rules.flatten
end end
def namespace_abilities user, namespace def namespace_abilities(user, namespace)
rules = [] rules = []
# Only namespace owner and administrators can manage it # Only namespace owner and administrators can manage it
......
...@@ -88,9 +88,24 @@ class Commit ...@@ -88,9 +88,24 @@ class Commit
description.present? description.present?
end end
def hook_attrs(project)
path_with_namespace = project.path_with_namespace
{
id: id,
message: safe_message,
timestamp: committed_date.xmlschema,
url: "#{Gitlab.config.gitlab.url}/#{path_with_namespace}/commit/#{id}",
author: {
name: author_name,
email: author_email
}
}
end
# Discover issues should be closed when this commit is pushed to a project's # Discover issues should be closed when this commit is pushed to a project's
# default branch. # default branch.
def closes_issues project def closes_issues(project)
Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project) Gitlab::ClosingIssueExtractor.closed_by_message_in_project(safe_message, project)
end end
......
...@@ -134,7 +134,7 @@ module Issuable ...@@ -134,7 +134,7 @@ module Issuable
def to_hook_data def to_hook_data
{ {
object_kind: self.class.name.underscore, object_kind: self.class.name.underscore,
object_attributes: self.attributes object_attributes: hook_attrs
} }
end end
......
...@@ -10,7 +10,7 @@ module Mentionable ...@@ -10,7 +10,7 @@ module Mentionable
module ClassMethods module ClassMethods
# Indicate which attributes of the Mentionable to search for GFM references. # Indicate which attributes of the Mentionable to search for GFM references.
def attr_mentionable *attrs def attr_mentionable(*attrs)
mentionable_attrs.concat(attrs.map(&:to_s)) mentionable_attrs.concat(attrs.map(&:to_s))
end end
...@@ -38,7 +38,7 @@ module Mentionable ...@@ -38,7 +38,7 @@ module Mentionable
# Determine whether or not a cross-reference Note has already been created between this Mentionable and # Determine whether or not a cross-reference Note has already been created between this Mentionable and
# the specified target. # the specified target.
def has_mentioned? target def has_mentioned?(target)
Note.cross_reference_exists?(target, local_reference) Note.cross_reference_exists?(target, local_reference)
end end
...@@ -64,15 +64,17 @@ module Mentionable ...@@ -64,15 +64,17 @@ module Mentionable
end end
# Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference. # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
def references p = project, text = mentionable_text def references(p = project, text = mentionable_text)
return [] if text.blank? return [] if text.blank?
ext = Gitlab::ReferenceExtractor.new ext = Gitlab::ReferenceExtractor.new
ext.analyze(text) ext.analyze(text, p)
(ext.issues_for(p) + ext.merge_requests_for(p) + ext.commits_for(p)).uniq - [local_reference] (ext.issues_for +
ext.merge_requests_for +
ext.commits_for).uniq - [local_reference]
end end
# Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+. # Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
def create_cross_references! p = project, a = author, without = [] def create_cross_references!(p = project, a = author, without = [])
refs = references(p) - without refs = references(p) - without
refs.each do |ref| refs.each do |ref|
Note.create_cross_reference_note(ref, local_reference, a, p) Note.create_cross_reference_note(ref, local_reference, a, p)
...@@ -81,7 +83,7 @@ module Mentionable ...@@ -81,7 +83,7 @@ module Mentionable
# If the mentionable_text field is about to change, locate any *added* references and create cross references for # If the mentionable_text field is about to change, locate any *added* references and create cross references for
# them. Invoke from an observer's #before_save implementation. # them. Invoke from an observer's #before_save implementation.
def notice_added_references p = project, a = author def notice_added_references(p = project, a = author)
ch = changed_attributes ch = changed_attributes
original, mentionable_changed = "", false original, mentionable_changed = "", false
self.class.mentionable_attrs.each do |attr| self.class.mentionable_attrs.each do |attr|
......
# Contains functionality for objects that can have task lists in their
# descriptions. Task list items can be added with Markdown like "* [x] Fix
# bugs".
#
# Used by MergeRequest and Issue
module Taskable
TASK_PATTERN_MD = /^(?<bullet> *[*-] *)\[(?<checked>[ xX])\]/.freeze
TASK_PATTERN_HTML = /^<li>\[(?<checked>[ xX])\]/.freeze
# Change the state of a task list item for this Taskable. Edit the object's
# description by finding the nth task item and changing its checkbox
# placeholder to "[x]" if +checked+ is true, or "[ ]" if it's false.
# Note: task numbering starts with 1
def update_nth_task(n, checked)
index = 0
check_char = checked ? 'x' : ' '
# Do this instead of using #gsub! so that ActiveRecord detects that a field
# has changed.
self.description = self.description.gsub(TASK_PATTERN_MD) do |match|
index += 1
case index
when n then "#{$LAST_MATCH_INFO[:bullet]}[#{check_char}]"
else match
end
end
save
end
# Return true if this object's description has any task list items.
def tasks?
description && description.match(TASK_PATTERN_MD)
end
# Return a string that describes the current state of this Taskable's task
# list items, e.g. "20 tasks (12 done, 8 unfinished)"
def task_status
return nil unless description
num_tasks = 0
num_done = 0
description.scan(TASK_PATTERN_MD) do
num_tasks += 1
num_done += 1 unless $LAST_MATCH_INFO[:checked] == ' '
end
"#{num_tasks} tasks (#{num_done} done, #{num_tasks - num_done} unfinished)"
end
end
...@@ -21,6 +21,7 @@ class WebHook < ActiveRecord::Base ...@@ -21,6 +21,7 @@ class WebHook < ActiveRecord::Base
default_value_for :push_events, true default_value_for :push_events, true
default_value_for :issues_events, false default_value_for :issues_events, false
default_value_for :merge_requests_events, false default_value_for :merge_requests_events, false
default_value_for :tag_push_events, false
# HTTParty timeout # HTTParty timeout
default_timeout Gitlab.config.gitlab.webhook_timeout default_timeout Gitlab.config.gitlab.webhook_timeout
......
...@@ -23,6 +23,7 @@ require 'file_size_validator' ...@@ -23,6 +23,7 @@ require 'file_size_validator'
class Issue < ActiveRecord::Base class Issue < ActiveRecord::Base
include Issuable include Issuable
include InternalId include InternalId
include Taskable
ActsAsTaggableOn.strict_case_match = true ActsAsTaggableOn.strict_case_match = true
...@@ -48,6 +49,10 @@ class Issue < ActiveRecord::Base ...@@ -48,6 +49,10 @@ class Issue < ActiveRecord::Base
state :closed state :closed
end end
def hook_attrs
attributes
end
# Mentionable overrides. # Mentionable overrides.
def gfm_reference def gfm_reference
......
...@@ -77,7 +77,7 @@ class ProjectMember < Member ...@@ -77,7 +77,7 @@ class ProjectMember < Member
false false
end end
def truncate_team project def truncate_team(project)
truncate_teams [project.id] truncate_teams [project.id]
end end
......
...@@ -25,6 +25,7 @@ require Rails.root.join("lib/static_model") ...@@ -25,6 +25,7 @@ require Rails.root.join("lib/static_model")
class MergeRequest < ActiveRecord::Base class MergeRequest < ActiveRecord::Base
include Issuable include Issuable
include Taskable
include InternalId include InternalId
belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project" belongs_to :target_project, foreign_key: :target_project_id, class_name: "Project"
...@@ -211,6 +212,20 @@ class MergeRequest < ActiveRecord::Base ...@@ -211,6 +212,20 @@ class MergeRequest < ActiveRecord::Base
Gitlab::Satellite::MergeAction.new(current_user, self).format_patch Gitlab::Satellite::MergeAction.new(current_user, self).format_patch
end end
def hook_attrs
attrs = {
source: source_project.hook_attrs,
target: target_project.hook_attrs,
last_commit: nil
}
unless last_commit.nil?
attrs.merge!(last_commit: last_commit.hook_attrs(source_project))
end
attributes.merge!(attrs)
end
def for_fork? def for_fork?
target_project != source_project target_project != source_project
end end
......
...@@ -38,7 +38,7 @@ class Namespace < ActiveRecord::Base ...@@ -38,7 +38,7 @@ class Namespace < ActiveRecord::Base
scope :root, -> { where('type IS NULL') } scope :root, -> { where('type IS NULL') }
def self.search query def self.search(query)
where("name LIKE :query OR path LIKE :query", query: "%#{query}%") where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
end end
......
...@@ -6,7 +6,7 @@ module Network ...@@ -6,7 +6,7 @@ module Network
@max_count ||= 650 @max_count ||= 650
end end
def initialize project, ref, commit, filter_ref def initialize(project, ref, commit, filter_ref)
@project = project @project = project
@ref = ref @ref = ref
@commit = commit @commit = commit
......
...@@ -47,7 +47,7 @@ class Note < ActiveRecord::Base ...@@ -47,7 +47,7 @@ class Note < ActiveRecord::Base
scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) }
scope :inline, ->{ where("line_code IS NOT NULL") } scope :inline, ->{ where("line_code IS NOT NULL") }
scope :not_inline, ->{ where(line_code: [nil, '']) } scope :not_inline, ->{ where(line_code: [nil, '']) }
scope :system, ->{ where(system: true) }
scope :common, ->{ where(noteable_type: ["", nil]) } scope :common, ->{ where(noteable_type: ["", nil]) }
scope :fresh, ->{ order("created_at ASC, id ASC") } scope :fresh, ->{ order("created_at ASC, id ASC") }
scope :inc_author_project, ->{ includes(:project, :author) } scope :inc_author_project, ->{ includes(:project, :author) }
...@@ -70,13 +70,17 @@ class Note < ActiveRecord::Base ...@@ -70,13 +70,17 @@ class Note < ActiveRecord::Base
) )
end end
# +noteable+ was referenced from +mentioner+, by including GFM in either +mentioner+'s description or an associated Note. # +noteable+ was referenced from +mentioner+, by including GFM in either
# Create a system Note associated with +noteable+ with a GFM back-reference to +mentioner+. # +mentioner+'s description or an associated Note.
# Create a system Note associated with +noteable+ with a GFM back-reference
# to +mentioner+.
def create_cross_reference_note(noteable, mentioner, author, project) def create_cross_reference_note(noteable, mentioner, author, project)
gfm_reference = mentioner_gfm_ref(noteable, mentioner, project)
note_options = { note_options = {
project: project, project: project,
author: author, author: author,
note: "_mentioned in #{mentioner.gfm_reference}_", note: "_mentioned in #{gfm_reference}_",
system: true system: true
} }
...@@ -163,12 +167,78 @@ class Note < ActiveRecord::Base ...@@ -163,12 +167,78 @@ class Note < ActiveRecord::Base
# Determine whether or not a cross-reference note already exists. # Determine whether or not a cross-reference note already exists.
def cross_reference_exists?(noteable, mentioner) def cross_reference_exists?(noteable, mentioner)
where(noteable_id: noteable.id, system: true, note: "_mentioned in #{mentioner.gfm_reference}_").any? gfm_reference = mentioner_gfm_ref(noteable, mentioner)
notes = if noteable.is_a?(Commit)
where(commit_id: noteable.id)
else
where(noteable_id: noteable.id)
end
notes.where('note like ?', "_mentioned in #{gfm_reference}_").
system.any?
end end
def search(query) def search(query)
where("note like :query", query: "%#{query}%") where("note like :query", query: "%#{query}%")
end end
private
# Prepend the mentioner's namespaced project path to the GFM reference for
# cross-project references. For same-project references, return the
# unmodified GFM reference.
def mentioner_gfm_ref(noteable, mentioner, project = nil)
if mentioner.is_a?(Commit)
if project.nil?
return mentioner.gfm_reference.sub('commit ', 'commit %')
else
mentioning_project = project
end
else
mentioning_project = mentioner.project
end
noteable_project_id = noteable_project_id(noteable, mentioning_project)
full_gfm_reference(mentioning_project, noteable_project_id, mentioner)
end
# Return the ID of the project that +noteable+ belongs to, or nil if
# +noteable+ is a commit and is not part of the project that owns
# +mentioner+.
def noteable_project_id(noteable, mentioning_project)
if noteable.is_a?(Commit)
if mentioning_project.repository.commit(noteable.id)
# The noteable commit belongs to the mentioner's project
mentioning_project.id
else
nil
end
else
noteable.project.id
end
end
# Return the +mentioner+ GFM reference. If the mentioner and noteable
# projects are not the same, add the mentioning project's path to the
# returned value.
def full_gfm_reference(mentioning_project, noteable_project_id, mentioner)
if mentioning_project.id == noteable_project_id
mentioner.gfm_reference
else
if mentioner.is_a?(Commit)
mentioner.gfm_reference.sub(
/(commit )/,
"\\1#{mentioning_project.path_with_namespace}@"
)
else
mentioner.gfm_reference.sub(
/(issue |merge request )/,
"\\1#{mentioning_project.path_with_namespace}"
)
end
end
end
end end
def commit_author def commit_author
......
...@@ -65,6 +65,7 @@ class Project < ActiveRecord::Base ...@@ -65,6 +65,7 @@ class Project < ActiveRecord::Base
has_one :gemnasium_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy
has_one :slack_service, dependent: :destroy has_one :slack_service, dependent: :destroy
has_one :buildbox_service, dependent: :destroy has_one :buildbox_service, dependent: :destroy
has_one :pushover_service, dependent: :destroy
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id" has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
has_one :forked_from_project, through: :forked_project_link has_one :forked_from_project, through: :forked_project_link
# Merge Requests for target project should be removed with it # Merge Requests for target project should be removed with it
...@@ -312,8 +313,7 @@ class Project < ActiveRecord::Base ...@@ -312,8 +313,7 @@ class Project < ActiveRecord::Base
end end
def available_services_names def available_services_names
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack pushover buildbox)
emails_on_push gemnasium slack buildbox)
end end
def gitlab_ci? def gitlab_ci?
...@@ -333,7 +333,7 @@ class Project < ActiveRecord::Base ...@@ -333,7 +333,7 @@ class Project < ActiveRecord::Base
path path
end end
def items_for entity def items_for(entity)
case entity case entity
when 'issue' then when 'issue' then
issues issues
...@@ -506,7 +506,7 @@ class Project < ActiveRecord::Base ...@@ -506,7 +506,7 @@ class Project < ActiveRecord::Base
end end
# Check if current branch name is marked as protected in the system # Check if current branch name is marked as protected in the system
def protected_branch? branch_name def protected_branch?(branch_name)
protected_branches_names.include?(branch_name) protected_branches_names.include?(branch_name)
end end
...@@ -546,6 +546,16 @@ class Project < ActiveRecord::Base ...@@ -546,6 +546,16 @@ class Project < ActiveRecord::Base
end end
end end
def hook_attrs
{
name: name,
ssh_url: ssh_url_to_repo,
http_url: http_url_to_repo,
namespace: namespace.name,
visibility_level: visibility_level
}
end
# Reset events cache related to this project # Reset events cache related to this project
# #
# Since we do cache @event we need to reset cache in special cases: # Since we do cache @event we need to reset cache in special cases:
......
...@@ -27,7 +27,7 @@ class GitlabCiService < CiService ...@@ -27,7 +27,7 @@ class GitlabCiService < CiService
hook.save hook.save
end end
def commit_status_path sha def commit_status_path(sha)
project_url + "/builds/#{sha}/status.json?token=#{token}" project_url + "/builds/#{sha}/status.json?token=#{token}"
end end
...@@ -54,7 +54,7 @@ class GitlabCiService < CiService ...@@ -54,7 +54,7 @@ class GitlabCiService < CiService
end end
end end
def build_page sha def build_page(sha)
project_url + "/builds/#{sha}" project_url + "/builds/#{sha}"
end end
......
# == Schema Information
#
# Table name: services
#
# id :integer not null, primary key
# type :string(255)
# title :string(255)
# project_id :integer not null
# created_at :datetime
# updated_at :datetime
# active :boolean default(FALSE), not null
# properties :text
#
class PushoverService < Service
include HTTParty
base_uri 'https://api.pushover.net/1'
prop_accessor :api_key, :user_key, :device, :priority, :sound
validates :api_key, :user_key, :priority, presence: true, if: :activated?
def title
'Pushover'
end
def description
'Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop.'
end
def to_param
'pushover'
end
def fields
[
{ type: 'text', name: 'api_key', placeholder: 'Your application key' },
{ type: 'text', name: 'user_key', placeholder: 'Your user key' },
{ type: 'text', name: 'device', placeholder: 'Leave blank for all active devices' },
{ type: 'select', name: 'priority', choices:
[
['Lowest Priority', -2],
['Low Priority', -1],
['Normal Priority', 0],
['High Priority', 1]
],
default_choice: 0
},
{ type: 'select', name: 'sound', choices:
[
['Device default sound', nil],
['Pushover (default)', 'pushover'],
['Bike', 'bike'],
['Bugle', 'bugle'],
['Cash Register', 'cashregister'],
['Classical', 'classical'],
['Cosmic', 'cosmic'],
['Falling', 'falling'],
['Gamelan', 'gamelan'],
['Incoming', 'incoming'],
['Intermission', 'intermission'],
['Magic', 'magic'],
['Mechanical', 'mechanical'],
['Piano Bar', 'pianobar'],
['Siren', 'siren'],
['Space Alarm', 'spacealarm'],
['Tug Boat', 'tugboat'],
['Alien Alarm (long)', 'alien'],
['Climb (long)', 'climb'],
['Persistent (long)', 'persistent'],
['Pushover Echo (long)', 'echo'],
['Up Down (long)', 'updown'],
['None (silent)', 'none']
]
},
]
end
def execute(push_data)
ref = push_data[:ref].gsub('refs/heads/', '')
before = push_data[:before]
after = push_data[:after]
if before =~ /000000/
message = "#{push_data[:user_name]} pushed new branch \"#{ref}\"."
elsif after =~ /000000/
message = "#{push_data[:user_name]} deleted branch \"#{ref}\"."
else
message = "#{push_data[:user_name]} push to branch \"#{ref}\"."
end
if push_data[:total_commits_count] > 0
message << "\nTotal commits count: #{push_data[:total_commits_count]}"
end
pushover_data = {
token: api_key,
user: user_key,
device: device,
priority: priority,
title: "#{project.name_with_namespace}",
message: message,
url: push_data[:repository][:homepage],
url_title: "See project #{project.name_with_namespace}"
}
# Sound parameter MUST NOT be sent to API if not selected
if sound
pushover_data.merge!(sound: sound)
end
PushoverService.post('/messages.json', body: pushover_data)
end
end
...@@ -13,10 +13,8 @@ ...@@ -13,10 +13,8 @@
# #
class SlackService < Service class SlackService < Service
prop_accessor :room, :subdomain, :token prop_accessor :webhook
validates :room, presence: true, if: :activated? validates :webhook, presence: true, if: :activated?
validates :subdomain, presence: true, if: :activated?
validates :token, presence: true, if: :activated?
def title def title
'Slack' 'Slack'
...@@ -32,9 +30,7 @@ class SlackService < Service ...@@ -32,9 +30,7 @@ class SlackService < Service
def fields def fields
[ [
{ type: 'text', name: 'subdomain', placeholder: '' }, { type: 'text', name: 'webhook', placeholder: '' }
{ type: 'text', name: 'token', placeholder: '' },
{ type: 'text', name: 'room', placeholder: 'Ex. #general' },
] ]
end end
...@@ -44,10 +40,13 @@ class SlackService < Service ...@@ -44,10 +40,13 @@ class SlackService < Service
project_name: project_name project_name: project_name
)) ))
notifier = Slack::Notifier.new(subdomain, token) credentials = webhook.match(/(\w*).slack.com.*services\/(.*)/)
notifier.channel = room if credentials.present?
notifier.username = 'GitLab' subdomain = credentials[1]
notifier.ping(message.pretext, attachments: message.attachments) token = credentials[2].split("token=").last
notifier = Slack::Notifier.new(subdomain, token)
notifier.ping(message.pretext, attachments: message.attachments)
end
end end
private private
......
...@@ -11,7 +11,7 @@ class ProjectTeam ...@@ -11,7 +11,7 @@ class ProjectTeam
# @team << [@user, :master] # @team << [@user, :master]
# @team << [@users, :master] # @team << [@users, :master]
# #
def << args def <<(args)
users = args.first users = args.first
if users.respond_to?(:each) if users.respond_to?(:each)
......
...@@ -32,7 +32,7 @@ class Snippet < ActiveRecord::Base ...@@ -32,7 +32,7 @@ class Snippet < ActiveRecord::Base
validates :content, presence: true validates :content, presence: true
# Scopes # Scopes
scope :are_public, -> { where(private: false) } scope :are_internal, -> { where(private: false) }
scope :are_private, -> { where(private: true) } scope :are_private, -> { where(private: true) }
scope :fresh, -> { order("created_at DESC") } scope :fresh, -> { order("created_at DESC") }
scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) } scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) }
......
...@@ -15,7 +15,7 @@ class Tree ...@@ -15,7 +15,7 @@ class Tree
# by markup renderer. # by markup renderer.
if available_readmes.length > 1 if available_readmes.length > 1
supported_readmes = available_readmes.select do |readme| supported_readmes = available_readmes.select do |readme|
gitlab_markdown?(readme.name) || markup?(readme.name) previewable?(readme.name)
end end
# Take the first supported readme, or the first available readme, if we # Take the first supported readme, or the first available readme, if we
......
...@@ -203,7 +203,7 @@ class User < ActiveRecord::Base ...@@ -203,7 +203,7 @@ class User < ActiveRecord::Base
User.where(name: name).first User.where(name: name).first
end end
def filter filter_name def filter(filter_name)
case filter_name case filter_name
when "admins"; self.admins when "admins"; self.admins
when "blocked"; self.blocked when "blocked"; self.blocked
...@@ -213,7 +213,7 @@ class User < ActiveRecord::Base ...@@ -213,7 +213,7 @@ class User < ActiveRecord::Base
end end
end end
def search query def search(query)
where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%") where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%")
end end
...@@ -332,7 +332,7 @@ class User < ActiveRecord::Base ...@@ -332,7 +332,7 @@ class User < ActiveRecord::Base
several_namespaces? || admin several_namespaces? || admin
end end
def can? action, subject def can?(action, subject)
abilities.allowed?(self, action, subject) abilities.allowed?(self, action, subject)
end end
...@@ -353,7 +353,7 @@ class User < ActiveRecord::Base ...@@ -353,7 +353,7 @@ class User < ActiveRecord::Base
(personal_projects.count.to_f / projects_limit) * 100 (personal_projects.count.to_f / projects_limit) * 100
end end
def recent_push project_id = nil def recent_push(project_id = nil)
# Get push events not earlier than 2 hours ago # Get push events not earlier than 2 hours ago
events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours) events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours)
events = events.where(project_id: project_id) if project_id events = events.where(project_id: project_id) if project_id
...@@ -382,11 +382,11 @@ class User < ActiveRecord::Base ...@@ -382,11 +382,11 @@ class User < ActiveRecord::Base
project.team_member_by_id(self.id) project.team_member_by_id(self.id)
end end
def already_forked? project def already_forked?(project)
!!fork_of(project) !!fork_of(project)
end end
def fork_of project def fork_of(project)
links = ForkedProjectLink.where(forked_from_project_id: project, forked_to_project_id: personal_projects) links = ForkedProjectLink.where(forked_from_project_id: project, forked_to_project_id: personal_projects)
if links.any? if links.any?
...@@ -512,7 +512,7 @@ class User < ActiveRecord::Base ...@@ -512,7 +512,7 @@ class User < ActiveRecord::Base
NotificationService.new NotificationService.new
end end
def log_info message def log_info(message)
Gitlab::AppLogger.info message Gitlab::AppLogger.info message
end end
......
...@@ -25,7 +25,7 @@ class BaseService ...@@ -25,7 +25,7 @@ class BaseService
EventCreateService.new EventCreateService.new
end end
def log_info message def log_info(message)
Gitlab::AppLogger.info message Gitlab::AppLogger.info message
end end
......
...@@ -75,7 +75,7 @@ class GitPushService ...@@ -75,7 +75,7 @@ class GitPushService
# Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched, # Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched,
# close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables. # close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables.
def process_commit_messages ref def process_commit_messages(ref)
is_default_branch = is_default_branch?(ref) is_default_branch = is_default_branch?(ref)
@push_commits.each do |commit| @push_commits.each do |commit|
...@@ -150,49 +150,40 @@ class GitPushService ...@@ -150,49 +150,40 @@ class GitPushService
# will be passed as post receive hook data. # will be passed as post receive hook data.
# #
push_commits_limited.each do |commit| push_commits_limited.each do |commit|
data[:commits] << { data[:commits] << commit.hook_attrs(project)
id: commit.id,
message: commit.safe_message,
timestamp: commit.committed_date.xmlschema,
url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/#{commit.id}",
author: {
name: commit.author_name,
email: commit.author_email
}
}
end end
data data
end end
def push_to_existing_branch? ref, oldrev def push_to_existing_branch?(ref, oldrev)
ref_parts = ref.split('/') ref_parts = ref.split('/')
# Return if this is not a push to a branch (e.g. new commits) # Return if this is not a push to a branch (e.g. new commits)
ref_parts[1] =~ /heads/ && oldrev != "0000000000000000000000000000000000000000" ref_parts[1] =~ /heads/ && oldrev != "0000000000000000000000000000000000000000"
end end
def push_to_new_branch? ref, oldrev def push_to_new_branch?(ref, oldrev)
ref_parts = ref.split('/') ref_parts = ref.split('/')
ref_parts[1] =~ /heads/ && oldrev == "0000000000000000000000000000000000000000" ref_parts[1] =~ /heads/ && oldrev == "0000000000000000000000000000000000000000"
end end
def push_remove_branch? ref, newrev def push_remove_branch?(ref, newrev)
ref_parts = ref.split('/') ref_parts = ref.split('/')
ref_parts[1] =~ /heads/ && newrev == "0000000000000000000000000000000000000000" ref_parts[1] =~ /heads/ && newrev == "0000000000000000000000000000000000000000"
end end
def push_to_branch? ref def push_to_branch?(ref)
ref =~ /refs\/heads/ ref =~ /refs\/heads/
end end
def is_default_branch? ref def is_default_branch?(ref)
ref == "refs/heads/#{project.default_branch}" ref == "refs/heads/#{project.default_branch}"
end end
def commit_user commit def commit_user(commit)
User.find_for_commit(commit.author_email, commit.author_name) || user User.find_for_commit(commit.author_email, commit.author_name) || user
end end
end end
...@@ -8,9 +8,14 @@ module Issues ...@@ -8,9 +8,14 @@ module Issues
Issues::ReopenService.new(project, current_user, {}).execute(issue) Issues::ReopenService.new(project, current_user, {}).execute(issue)
when 'close' when 'close'
Issues::CloseService.new(project, current_user, {}).execute(issue) Issues::CloseService.new(project, current_user, {}).execute(issue)
when 'task_check'
issue.update_nth_task(params[:task_num].to_i, true)
when 'task_uncheck'
issue.update_nth_task(params[:task_num].to_i, false)
end end
if params.present? && issue.update_attributes(params.except(:state_event)) if params.present? && issue.update_attributes(params.except(:state_event,
:task_num))
issue.reset_events_cache issue.reset_events_cache
if issue.previous_changes.include?('milestone_id') if issue.previous_changes.include?('milestone_id')
...@@ -28,5 +33,12 @@ module Issues ...@@ -28,5 +33,12 @@ module Issues
issue issue
end end
private
def update_task(issue, params, checked)
issue.update_nth_task(params[:task_num].to_i, checked)
params.except!(:task_num)
end
end end
end end
...@@ -17,9 +17,15 @@ module MergeRequests ...@@ -17,9 +17,15 @@ module MergeRequests
MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request) MergeRequests::ReopenService.new(project, current_user, {}).execute(merge_request)
when 'close' when 'close'
MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request) MergeRequests::CloseService.new(project, current_user, {}).execute(merge_request)
when 'task_check'
merge_request.update_nth_task(params[:task_num].to_i, true)
when 'task_uncheck'
merge_request.update_nth_task(params[:task_num].to_i, false)
end end
if params.present? && merge_request.update_attributes(params.except(:state_event)) if params.present? && merge_request.update_attributes(
params.except(:state_event, :task_num)
)
merge_request.reset_events_cache merge_request.reset_events_cache
if merge_request.previous_changes.include?('milestone_id') if merge_request.previous_changes.include?('milestone_id')
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.panel-body .panel-body
- if @sidekiq_processes.empty? - if @sidekiq_processes.empty?
%h4.cred %h4.cred
%i.icon-warning-sign %i.fa.fa-exclamation-triangle
There are no running sidekiq processes. Please restart GitLab There are no running sidekiq processes. Please restart GitLab
- else - else
%table.table %table.table
...@@ -32,10 +32,10 @@ ...@@ -32,10 +32,10 @@
.clearfix .clearfix
%p %p
%i.icon-exclamation-sign %i.fa.fa-exclamation-circle
If '[25 of 25 busy]' is shown, restart GitLab with 'sudo service gitlab reload'. If '[25 of 25 busy]' is shown, restart GitLab with 'sudo service gitlab reload'.
%p %p
%i.icon-exclamation-sign %i.fa.fa-exclamation-circle
If more than one sidekiq process is listed, stop GitLab, kill the remaining sidekiq processes (sudo pkill -u #{Settings.gitlab.user} -f sidekiq) and restart GitLab. If more than one sidekiq process is listed, stop GitLab, kill the remaining sidekiq processes (sudo pkill -u #{Settings.gitlab.user} -f sidekiq) and restart GitLab.
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
%p.light %p.light
Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more. Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more.
.broadcast-message-preview .broadcast-message-preview
%i.icon-bullhorn %i.fa.fa-bullhorn
%span Your message here %span Your message here
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal'} do |f| = form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal'} do |f|
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#{broadcast_message.ends_at.to_s(:short)} #{broadcast_message.ends_at.to_s(:short)}
&nbsp; &nbsp;
= link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-tiny' do = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-tiny' do
%i.icon-remove.cred %i.fa.fa-times.cred
.message= broadcast_message.message .message= broadcast_message.message
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
= f.label :avatar, "Group avatar", class: 'control-label' = f.label :avatar, "Group avatar", class: 'control-label'
.col-sm-10 .col-sm-10
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button %a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.icon-paper-clip %i.fa.fa-paperclip
%span Choose File ... %span Choose File ...
&nbsp; &nbsp;
%span.file_name.js-avatar-filename File name... %span.file_name.js-avatar-filename File name...
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
%h4 %h4
= link_to [:admin, group] do = link_to [:admin, group] do
%i.icon-folder-close %i.fa.fa-folder
= group.name = group.name
&rarr; &rarr;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
Group: #{@group.name} Group: #{@group.name}
= link_to edit_admin_group_path(@group), class: "btn pull-right" do = link_to edit_admin_group_path(@group), class: "btn pull-right" do
%i.icon-edit %i.fa.fa-pencil-square-o
Edit Edit
%hr %hr
.row .row
...@@ -81,6 +81,6 @@ ...@@ -81,6 +81,6 @@
%span.pull-right.light %span.pull-right.light
= member.human_access = member.human_access
= link_to group_group_members_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do = link_to group_group_members_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.icon-minus.icon-white %i.fa.fa-minus.fa-inverse
.panel-footer .panel-footer
= paginate @members, param_name: 'members_page', theme: 'gitlab' = paginate @members, param_name: 'members_page', theme: 'gitlab'
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
.tab-pane.active#githost .tab-pane.active#githost
.file-holder#README .file-holder#README
.file-title .file-title
%i.icon-file %i.fa.fa-file
githost.log githost.log
.pull-right .pull-right
= link_to '#', class: 'log-bottom' do = link_to '#', class: 'log-bottom' do
%i.icon-arrow-down %i.fa.fa-arrow-down
Scroll down Scroll down
.file-content.logs .file-content.logs
%ol %ol
...@@ -27,11 +27,11 @@ ...@@ -27,11 +27,11 @@
.tab-pane#application .tab-pane#application
.file-holder#README .file-holder#README
.file-title .file-title
%i.icon-file %i.fa.fa-file
application.log application.log
.pull-right .pull-right
= link_to '#', class: 'log-bottom' do = link_to '#', class: 'log-bottom' do
%i.icon-arrow-down %i.fa.fa-arrow-down
Scroll down Scroll down
.file-content.logs .file-content.logs
%ol %ol
...@@ -41,11 +41,11 @@ ...@@ -41,11 +41,11 @@
.tab-pane#production .tab-pane#production
.file-holder#README .file-holder#README
.file-title .file-title
%i.icon-file %i.fa.fa-file
production.log production.log
.pull-right .pull-right
= link_to '#', class: 'log-bottom' do = link_to '#', class: 'log-bottom' do
%i.icon-arrow-down %i.fa.fa-arrow-down
Scroll down Scroll down
.file-content.logs .file-content.logs
%ol %ol
...@@ -55,11 +55,11 @@ ...@@ -55,11 +55,11 @@
.tab-pane#sidekiq .tab-pane#sidekiq
.file-holder#README .file-holder#README
.file-title .file-title
%i.icon-file %i.fa.fa-file
sidekiq.log sidekiq.log
.pull-right .pull-right
= link_to '#', class: 'log-bottom' do = link_to '#', class: 'log-bottom' do
%i.icon-arrow-down %i.fa.fa-arrow-down
Scroll down Scroll down
.file-content.logs .file-content.logs
%ol %ol
......
%h3.page-title %h3.page-title
Project: #{@project.name_with_namespace} Project: #{@project.name_with_namespace}
= link_to edit_project_path(@project), class: "btn pull-right" do = link_to edit_project_path(@project), class: "btn pull-right" do
%i.icon-edit %i.fa.fa-pencil-square-o
Edit Edit
%hr %hr
.row .row
...@@ -98,7 +98,7 @@ ...@@ -98,7 +98,7 @@
group members (#{@group.group_members.count}) group members (#{@group.group_members.count})
.pull-right .pull-right
= link_to admin_group_path(@group), class: 'btn btn-small' do = link_to admin_group_path(@group), class: 'btn btn-small' do
%i.icon-edit %i.fa.fa-pencil-square-o
%ul.well-list %ul.well-list
- @group_members.each do |member| - @group_members.each do |member|
= render 'groups/group_members/group_member', member: member, show_controls: false = render 'groups/group_members/group_member', member: member, show_controls: false
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
(#{@project.users.count}) (#{@project.users.count})
.pull-right .pull-right
= link_to project_team_index_path(@project), class: "btn btn-tiny" do = link_to project_team_index_path(@project), class: "btn btn-tiny" do
%i.icon-edit %i.fa.fa-pencil-square-o
Manage Access Manage Access
%ul.well-list.team_members %ul.well-list.team_members
- @project_members.each do |project_member| - @project_members.each do |project_member|
...@@ -127,6 +127,6 @@ ...@@ -127,6 +127,6 @@
- else - else
%span.light= project_member.human_access %span.light= project_member.human_access
= link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-small btn-remove" do = link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, remote: true, class: "btn btn-small btn-remove" do
%i.icon-remove %i.fa.fa-times
.panel-footer .panel-footer
= paginate @project_members, param_name: 'project_members_page', theme: 'gitlab' = paginate @project_members, param_name: 'project_members_page', theme: 'gitlab'
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
.form-group .form-group
= search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control' = search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control'
= button_tag class: 'btn btn-primary' do = button_tag class: 'btn btn-primary' do
%i.icon-search %i.fa.fa-search
%hr %hr
= link_to 'Reset', admin_users_path, class: "btn btn-cancel" = link_to 'Reset', admin_users_path, class: "btn btn-cancel"
...@@ -38,9 +38,9 @@ ...@@ -38,9 +38,9 @@
%li %li
.list-item-name .list-item-name
- if user.blocked? - if user.blocked?
%i.icon-lock.cred %i.fa.fa-lock.cred
- else - else
%i.icon-user.cgreen %i.fa.fa-user.cgreen
= link_to user.name, [:admin, user] = link_to user.name, [:admin, user]
- if user.admin? - if user.admin?
%strong.cred (Admin) %strong.cred (Admin)
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
%span.cred It's you! %span.cred It's you!
.pull-right .pull-right
%span.light %span.light
%i.icon-envelope %i.fa.fa-envelope
= mail_to user.email, user.email, class: 'light' = mail_to user.email, user.email, class: 'light'
&nbsp; &nbsp;
= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small" = link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn btn-small"
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.pull-right .pull-right
= link_to edit_admin_user_path(@user), class: "btn btn-grouped" do = link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
%i.icon-edit %i.fa.fa-pencil-square-o
Edit Edit
%hr %hr
%ul.nav.nav-tabs %ul.nav.nav-tabs
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
%span.light Secondary email: %span.light Secondary email:
%strong= email.email %strong= email.email
= link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-tiny btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do = link_to remove_email_admin_user_path(@user, email), data: { confirm: "Are you sure you want to remove #{email.email}?" }, method: :delete, class: "btn-tiny btn btn-remove pull-right", title: 'Remove secondary email', id: "remove_email_#{email.id}" do
%i.icon-remove %i.fa.fa-times
%li %li
%span.light Can create groups: %span.light Can create groups:
...@@ -86,6 +86,11 @@ ...@@ -86,6 +86,11 @@
- else - else
never never
%li
%span.light Sign-in count:
%strong
= @user.sign_in_count
- if @user.ldap_user? - if @user.ldap_user?
%li %li
%span.light LDAP uid: %span.light LDAP uid:
...@@ -172,7 +177,7 @@ ...@@ -172,7 +177,7 @@
%span.light= user_group.human_access %span.light= user_group.human_access
- unless user_group.owner? - unless user_group.owner?
= link_to group_group_member_path(group, user_group), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do = link_to group_group_member_path(group, user_group), data: { confirm: remove_user_from_group_message(group, @user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.icon-remove.icon-white %i.fa.fa-times.fa-inverse
- else - else
.nothing-here-block This user has no groups. .nothing-here-block This user has no groups.
...@@ -211,4 +216,4 @@ ...@@ -211,4 +216,4 @@
- if tm.respond_to? :project - if tm.respond_to? :project
= link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do = link_to project_team_member_path(project, @user), data: { confirm: remove_from_project_team_message(project, @user) }, remote: true, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from project' do
%i.icon-remove %i.fa.fa-times
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' = search_field_tag :filter_group, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
- if current_user.can_create_group? - if current_user.can_create_group?
= link_to new_group_path, class: "btn btn-new pull-right" do = link_to new_group_path, class: "btn btn-new pull-right" do
%i.icon-plus %i.fa.fa-plus
New group New group
%ul.well-list.dash-list %ul.well-list.dash-list
- groups.each do |group| - groups.each do |group|
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
%span.group-name.filter-title %span.group-name.filter-title
= truncate(group.name, length: 35) = truncate(group.name, length: 35)
%span.arrow %span.arrow
%i.icon-angle-right %i.fa.fa-angle-right
- if groups.blank? - if groups.blank?
%li %li
.nothing-here-block You have no groups yet. .nothing-here-block You have no groups yet.
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
%span.project-name.filter-title %span.project-name.filter-title
= project.name = project.name
%span.arrow %span.arrow
%i.icon-angle-right %i.fa.fa-angle-right
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control' = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'dash-filter form-control'
- if current_user.can_create_project? - if current_user.can_create_project?
= link_to new_project_path, class: "btn btn-new pull-right" do = link_to new_project_path, class: "btn btn-new pull-right" do
%i.icon-plus %i.fa.fa-plus
New project New project
%ul.well-list.dash-list %ul.well-list.dash-list
...@@ -21,4 +21,4 @@ ...@@ -21,4 +21,4 @@
.pull-right .pull-right
= link_to projects_dashboard_path do = link_to projects_dashboard_path do
Show all Show all
%i.icon-angle-right %i.fa.fa-angle-right
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
- @groups.each do |group| - @groups.each do |group|
%li{ class: (group.name == params[:group]) ? 'active' : 'light' } %li{ class: (group.name == params[:group]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(group: group.name) do = link_to projects_dashboard_filter_path(group: group.name) do
%i.icon-folder-close-alt %i.fa.fa-folder-o
= group.name = group.name
%small.pull-right %small.pull-right
= group.projects.count = group.projects.count
...@@ -51,5 +51,5 @@ ...@@ -51,5 +51,5 @@
- @tags.each do |tag| - @tags.each do |tag|
%li{ class: (tag.name == params[:tag]) ? 'active' : 'light' } %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
= link_to projects_dashboard_filter_path(scope: params[:scope], tag: tag.name) do = link_to projects_dashboard_filter_path(scope: params[:scope], tag: tag.name) do
%i.icon-tag %i.fa.fa-tag
= tag.name = tag.name
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
%span.rss-icon %span.rss-icon
= link_to dashboard_path(:atom, { private_token: current_user.private_token }) do = link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
%strong %strong
%i.icon-rss %i.fa.fa-rss
News Feed News Feed
%hr %hr
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
%hr %hr
%div %div
.dashboard-intro-icon .dashboard-intro-icon
%i.icon-bookmark-empty %i.fa.fa-bookmark-o
%div %div
%p.slead %p.slead
You don't have access to any projects right now. You don't have access to any projects right now.
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
%hr %hr
%div %div
.dashboard-intro-icon .dashboard-intro-icon
%i.icon-group %i.fa.fa-users
%div %div
%p.slead %p.slead
You can create a group for several dependent projects. You can create a group for several dependent projects.
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
%hr %hr
%div %div
.dashboard-intro-icon .dashboard-intro-icon
%i.icon-globe %i.fa.fa-globe
%div %div
%p.slead %p.slead
There are There are
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'shared/filter', entity: 'issue' = render 'shared/filter', entity: 'issue'
.col-md-9 .col-md-9
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
%hr %hr
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'shared/filter', entity: 'merge_request' = render 'shared/filter', entity: 'merge_request'
.col-md-9 .col-md-9
......
...@@ -40,23 +40,23 @@ ...@@ -40,23 +40,23 @@
- if current_user.can_leave_project?(project) - if current_user.can_leave_project?(project)
.pull-right .pull-right
= link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do = link_to leave_project_team_members_path(project), data: { confirm: "Leave project?"}, method: :delete, remote: true, class: "btn-tiny btn remove-row", title: 'Leave project' do
%i.icon-signout %i.fa.fa-sign-out
Leave Leave
- if project.forked_from_project - if project.forked_from_project
%small.pull-right %small.pull-right
%i.icon-code-fork %i.fa.fa-code-fork
Forked from: Forked from:
= link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project) = link_to project.forked_from_project.name_with_namespace, project_path(project.forked_from_project)
.project-info .project-info
.pull-right .pull-right
- if project.archived? - if project.archived?
%span.label %span.label
%i.icon-archive %i.fa.fa-archive
Archived Archived
- project.tags.each do |tag| - project.tags.each do |tag|
%span.label.label-info %span.label.label-info
%i.icon-tag %i.fa.fa-tag
= tag.name = tag.name
- if project.description.present? - if project.description.present?
%p= truncate project.description, length: 100 %p= truncate project.description, length: 100
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
= render 'sidebar' = render 'sidebar'
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
- else - else
= render "zero_authorized_projects" = render "zero_authorized_projects"
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
.event-body .event-body
.event-note .event-note
.md .md
%i.icon-comment-alt.event-note-icon %i.fa.fa-comment-o.event-note-icon
= event_note(event.target.note) = event_note(event.target.note)
- note = event.target - note = event.target
- if note.attachment.url - if note.attachment.url
...@@ -18,5 +18,5 @@ ...@@ -18,5 +18,5 @@
= image_tag note.attachment.secure_url, class: 'note-image-attach' = image_tag note.attachment.secure_url, class: 'note-image-attach'
- else - else
= link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do = link_to note.attachment.secure_url, target: "_blank", class: 'note-file-attach' do
%i.icon-paper-clip %i.fa.fa-paperclip
= note.attachment_identifier = note.attachment_identifier
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
.clearfix .clearfix
%h4 %h4
= link_to group_path(id: group.path) do = link_to group_path(id: group.path) do
%i.icon-group %i.fa.fa-users
= group.name = group.name
.clearfix .clearfix
%p %p
......
...@@ -21,5 +21,5 @@ ...@@ -21,5 +21,5 @@
&middot; &middot;
= link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project) = link_to pluralize(project.repository.tag_names.count, 'tag'), project_tags_path(project)
- else - else
%i.icon-warning-sign %i.fa.fa-exclamation-triangle
Empty repository Empty repository
.explore-trending-block .explore-trending-block
%p.lead %p.lead
%i.icon-comments-alt %i.fa.fa-comments-o
See most starred projects See most starred projects
%hr %hr
.public-projects .public-projects
......
.explore-trending-block .explore-trending-block
%p.lead %p.lead
%i.icon-comments-alt %i.fa.fa-comments-o
See most discussed projects for last month See most discussed projects for last month
%hr %hr
.public-projects .public-projects
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
- if can? current_user, :create_projects, @group - if can? current_user, :create_projects, @group
.panel-head-actions .panel-head-actions
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do
%i.icon-plus %i.fa.fa-plus
New project New project
%ul.well-list %ul.well-list
- if projects.blank? - if projects.blank?
...@@ -18,4 +18,4 @@ ...@@ -18,4 +18,4 @@
%span.project-name %span.project-name
= project.name = project.name
%span.arrow %span.arrow
%i.icon-angle-right %i.fa.fa-angle-right
%ul.nav.nav-pills.nav-stacked.nav-stacked-menu %ul.nav.nav-pills.nav-stacked.nav-stacked-menu
= nav_link(path: 'groups#edit') do = nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group) do = link_to edit_group_path(@group) do
%i.icon-edit %i.fa.fa-pencil-square-o
Group Group
= nav_link(path: 'groups#projects') do = nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group) do = link_to projects_group_path(@group) do
%i.icon-folder-close %i.fa.fa-folder
Projects Projects
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
- else - else
You can upload a group avatar here You can upload a group avatar here
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button %a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.icon-paper-clip %i.fa.fa-paperclip
%span Choose File ... %span Choose File ...
&nbsp; &nbsp;
%span.file_name.js-avatar-filename File name... %span.file_name.js-avatar-filename File name...
......
...@@ -15,14 +15,14 @@ ...@@ -15,14 +15,14 @@
- if show_controls - if show_controls
- if can?(current_user, :modify, member) - if can?(current_user, :modify, member)
= link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do = link_to '#', class: "btn-tiny btn js-toggle-button", title: 'Edit access level' do
%i.icon-edit %i.fa.fa-pencil-square-o
- if can?(current_user, :destroy, member) - if can?(current_user, :destroy, member)
- if current_user == member.user - if current_user == member.user
= link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do = link_to leave_profile_group_path(@group), data: { confirm: leave_group_message(@group.name)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.icon-minus.icon-white %i.fa.fa-minus.fa-inverse
- else - else
= link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do = link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.icon-minus.icon-white %i.fa.fa-minus.fa-inverse
.edit-member.hide.js-toggle-content .edit-member.hide.js-toggle-content
= form_for [@group, member], remote: true do |f| = form_for [@group, member], remote: true do |f|
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'shared/filter', entity: 'issue' = render 'shared/filter', entity: 'issue'
.col-md-9 .col-md-9
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
.pull-right .pull-right
= link_to '#', class: 'btn btn-new js-toggle-button' do = link_to '#', class: 'btn btn-new js-toggle-button' do
Add members Add members
%i.icon-chevron-down %i.fa.fa-chevron-down
.js-toggle-content.hide.new-group-member-holder .js-toggle-content.hide.new-group-member-holder
= render "new_group_member" = render "new_group_member"
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
%hr %hr
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'shared/filter', entity: 'merge_request' = render 'shared/filter', entity: 'merge_request'
.col-md-9 .col-md-9
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
.row .row
.fixed.sidebar-expand-button.hidden-lg.hidden-md .fixed.sidebar-expand-button.hidden-lg.hidden-md
%i.icon-list.icon-2x %i.fa.fa-list.fa-2x
.col-md-3.responsive-side .col-md-3.responsive-side
= render 'groups/filter', entity: 'milestone' = render 'groups/filter', entity: 'milestone'
.col-md-9 .col-md-9
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
= f.label :avatar, "Group avatar", class: 'control-label' = f.label :avatar, "Group avatar", class: 'control-label'
.col-sm-10 .col-sm-10
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button %a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.icon-paper-clip %i.fa.fa-paperclip
%span Choose File ... %span Choose File ...
&nbsp; &nbsp;
%span.file_name.js-avatar-filename File name... %span.file_name.js-avatar-filename File name...
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
- if can? current_user, :manage_group, @group - if can? current_user, :manage_group, @group
.panel-head-actions .panel-head-actions
= link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do = link_to new_project_path(namespace_id: @group.id), class: "btn btn-new" do
%i.icon-plus %i.fa.fa-plus
New Project New Project
%ul.well-list %ul.well-list
- @projects.each do |project| - @projects.each do |project|
......
...@@ -24,13 +24,13 @@ ...@@ -24,13 +24,13 @@
= @group.name = @group.name
- if @group.description.present? - if @group.description.present?
%p %p
= auto_link @group.description, link: :urls = escaped_autolink(@group.description)
= render "projects", projects: @projects = render "projects", projects: @projects
- if current_user - if current_user
.prepend-top-20 .prepend-top-20
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do = link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed" do
%strong %strong
%i.icon-rss %i.fa.fa-rss
News Feed News Feed
%hr %hr
......
...@@ -29,12 +29,12 @@ ...@@ -29,12 +29,12 @@
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-up %i.fa.fa-arrow-up
%td Move selection up %td Move selection up
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-down %i.fa.fa-arrow-down
%td Move selection down %td Move selection down
%tr %tr
%td.shortcut %td.shortcut
...@@ -132,28 +132,28 @@ ...@@ -132,28 +132,28 @@
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-left %i.fa.fa-arrow-left
\/ \/
.key h .key h
%td Scroll left %td Scroll left
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-right %i.fa.fa-arrow-right
\/ \/
.key l .key l
%td Scroll right %td Scroll right
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-up %i.fa.fa-arrow-up
\/ \/
.key k .key k
%td Scroll up %td Scroll up
%tr %tr
%td.shortcut %td.shortcut
.key .key
%i.icon-arrow-down %i.fa.fa-arrow-down
\/ \/
.key j .key j
%td Scroll down %td Scroll down
...@@ -161,7 +161,7 @@ ...@@ -161,7 +161,7 @@
%td.shortcut %td.shortcut
.key .key
shift shift
%i.icon-arrow-up %i.fa.fa-arrow-up
\/ \/
.key .key
shift k shift k
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
%td.shortcut %td.shortcut
.key .key
shift shift
%i.icon-arrow-down %i.fa.fa-arrow-down
\/ \/
.key .key
shift j shift j
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
%br %br
Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises. Used by more than 100,000 organizations, GitLab is the most popular solution to manage git repositories on-premises.
%br %br
Read more about GitLab at #{link_to "www.gitlab.com", "https://www.gitlab.com/", target: "_blank"}. Read more about GitLab at #{link_to promo_host, promo_url, target: '_blank'}.
%hr %hr
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
%ul.well-list %ul.well-list
%li %li
See our website for See our website for
= link_to "getting help", "https://www.gitlab.com/getting-help/" = link_to 'getting help', promo_url + '/getting-help/'
%li %li
Use the Use the
= link_to 'search bar', '#', onclick: 'Shortcuts.focusSearch(event)' = link_to 'search bar', '#', onclick: 'Shortcuts.focusSearch(event)'
......
- if broadcast_message.present? - if broadcast_message.present?
.broadcast-message{ style: broadcast_styling(broadcast_message) } .broadcast-message{ style: broadcast_styling(broadcast_message) }
%i.icon-bullhorn %i.fa.fa-bullhorn
= broadcast_message.message = broadcast_message.message
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
%button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"} %button.navbar-toggle{"data-target" => ".navbar-collapse", "data-toggle" => "collapse", type: "button"}
%span.sr-only Toggle navigation %span.sr-only Toggle navigation
%i.icon-reorder %i.fa.fa-bars
.navbar-collapse.collapse .navbar-collapse.collapse
%ul.nav.navbar-nav %ul.nav.navbar-nav
...@@ -18,31 +18,31 @@ ...@@ -18,31 +18,31 @@
= render "layouts/search" = render "layouts/search"
%li.visible-sm.visible-xs %li.visible-sm.visible-xs
= link_to search_path, title: "Search", class: 'has_bottom_tooltip', 'data-original-title' => 'Search area' do = link_to search_path, title: "Search", class: 'has_bottom_tooltip', 'data-original-title' => 'Search area' do
%i.icon-search %i.fa.fa-search
%li %li
= link_to help_path, title: 'Help', class: 'has_bottom_tooltip', = link_to help_path, title: 'Help', class: 'has_bottom_tooltip',
'data-original-title' => 'Help' do 'data-original-title' => 'Help' do
%i.icon-question-sign %i.fa.fa-question-circle
%li %li
= link_to explore_root_path, title: "Explore", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do = link_to explore_root_path, title: "Explore", class: 'has_bottom_tooltip', 'data-original-title' => 'Public area' do
%i.icon-globe %i.fa.fa-globe
%li %li
= link_to user_snippets_path(current_user), title: "My snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do = link_to user_snippets_path(current_user), title: "My snippets", class: 'has_bottom_tooltip', 'data-original-title' => 'My snippets' do
%i.icon-paste %i.fa.fa-clipboard
- if current_user.is_admin? - if current_user.is_admin?
%li %li
= link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do = link_to admin_root_path, title: "Admin area", class: 'has_bottom_tooltip', 'data-original-title' => 'Admin area' do
%i.icon-cogs %i.fa.fa-cogs
- if current_user.can_create_project? - if current_user.can_create_project?
%li %li
= link_to new_project_path, title: "New project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do = link_to new_project_path, title: "New project", class: 'has_bottom_tooltip', 'data-original-title' => 'New project' do
%i.icon-plus %i.fa.fa-plus
%li %li
= link_to profile_path, title: "Profile settings", class: 'has_bottom_tooltip', 'data-original-title' => 'Profile settings"' do = link_to profile_path, title: "Profile settings", class: 'has_bottom_tooltip', 'data-original-title' => 'Profile settings"' do
%i.icon-user %i.fa.fa-user
%li %li
= link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do = link_to destroy_user_session_path, class: "logout", method: :delete, title: "Logout", class: 'has_bottom_tooltip', 'data-original-title' => 'Logout' do
%i.icon-signout %i.fa.fa-sign-out
%li.hidden-xs %li.hidden-xs
= link_to current_user, class: "profile-pic", id: 'profile-pic' do = link_to current_user, class: "profile-pic", id: 'profile-pic' do
= image_tag avatar_icon(current_user.email, 26), alt: 'User activity' = image_tag avatar_icon(current_user.email, 26), alt: 'User activity'
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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