mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-17 08:36:06 +10:00
Merge branch 'master' into issue_12658
# Conflicts: # app/models/issue.rb # app/views/projects/_home_panel.html.haml # app/views/shared/projects/_project.html.haml # db/schema.rb # spec/models/project_spec.rb
This commit is contained in:
+1048
-1028
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,13 @@
|
||||
Please view this file on the master branch, on stable branches it's out of date.
|
||||
|
||||
v 8.6.0 (unreleased)
|
||||
- Add ability to move issue to another project
|
||||
- Prevent tokens in the import URL to be showed by the UI
|
||||
- Fix bug where wrong commit ID was being used in a merge request diff to show old image (Stan Hu)
|
||||
- Make HTTP(s) label consistent on clone bar (Stan Hu)
|
||||
- Add confidential issues
|
||||
- Bump gitlab_git to 9.0.3 (Stan Hu)
|
||||
- Fix diff image view modes (2-up, swipe, onion skin) not working (Stan Hu)
|
||||
- Support Golang subpackage fetching (Stan Hu)
|
||||
- Bump Capybara gem to 2.6.2 (Stan Hu)
|
||||
- New branch button appears on issues where applicable
|
||||
@@ -57,6 +61,7 @@ v 8.6.0 (unreleased)
|
||||
- User deletion is now done in the background so the request can not time out
|
||||
- Canceled builds are now ignored in compound build status if marked as `allowed to fail`
|
||||
- Trigger a todo for mentions on commits page
|
||||
- Let project owners and admins soft delete issues and merge requests
|
||||
|
||||
v 8.5.8
|
||||
- Bump Git version requirement to 2.7.4
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.6.5
|
||||
0.7.1
|
||||
|
||||
@@ -222,6 +222,8 @@ gem 'net-ssh', '~> 3.0.1'
|
||||
# Sentry integration
|
||||
gem 'sentry-raven', '~> 0.15'
|
||||
|
||||
gem 'premailer-rails', '~> 1.9.0'
|
||||
|
||||
# Metrics
|
||||
group :metrics do
|
||||
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
||||
@@ -285,7 +287,7 @@ group :development, :test do
|
||||
gem 'spring-commands-spinach', '~> 1.0.0'
|
||||
gem 'spring-commands-teaspoon', '~> 0.0.2'
|
||||
|
||||
gem 'rubocop', '~> 0.35.0', require: false
|
||||
gem 'rubocop', '~> 0.38.0', require: false
|
||||
gem 'scss_lint', '~> 0.47.0', require: false
|
||||
gem 'coveralls', '~> 0.8.2', require: false
|
||||
gem 'simplecov', '~> 0.10.0', require: false
|
||||
|
||||
+19
-11
@@ -61,9 +61,7 @@ GEM
|
||||
faraday_middleware-multi_json (~> 0.0)
|
||||
oauth2 (~> 1.0)
|
||||
asciidoctor (1.5.3)
|
||||
ast (2.1.0)
|
||||
astrolabe (1.3.1)
|
||||
parser (~> 2.2)
|
||||
ast (2.2.0)
|
||||
attr_encrypted (1.3.4)
|
||||
encryptor (>= 1.3.0)
|
||||
attr_required (1.0.0)
|
||||
@@ -150,6 +148,8 @@ GEM
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
creole (0.5.0)
|
||||
css_parser (1.3.7)
|
||||
addressable
|
||||
d3_rails (3.5.11)
|
||||
railties (>= 3.1.0)
|
||||
daemons (1.2.3)
|
||||
@@ -423,6 +423,7 @@ GEM
|
||||
haml (~> 4.0.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
ruby_parser (~> 3.5)
|
||||
htmlentities (4.3.4)
|
||||
http-cookie (1.0.2)
|
||||
domain_name (~> 0.5)
|
||||
http_parser.rb (0.5.3)
|
||||
@@ -554,8 +555,8 @@ GEM
|
||||
orm_adapter (0.5.0)
|
||||
paranoia (2.1.4)
|
||||
activerecord (~> 4.0)
|
||||
parser (2.2.3.0)
|
||||
ast (>= 1.1, < 3.0)
|
||||
parser (2.3.0.6)
|
||||
ast (~> 2.2)
|
||||
pg (0.18.4)
|
||||
poltergeist (1.9.0)
|
||||
capybara (~> 2.1)
|
||||
@@ -564,6 +565,12 @@ GEM
|
||||
websocket-driver (>= 0.2.0)
|
||||
posix-spawn (0.3.11)
|
||||
powerpack (0.1.1)
|
||||
premailer (1.8.6)
|
||||
css_parser (>= 1.3.6)
|
||||
htmlentities (>= 4.0.0)
|
||||
premailer-rails (1.9.0)
|
||||
actionmailer (>= 3, < 5)
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
pry (0.10.3)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
@@ -615,7 +622,7 @@ GEM
|
||||
activesupport (= 4.2.5.2)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.0.0)
|
||||
rainbow (2.1.0)
|
||||
raindrops (0.15.0)
|
||||
rake (10.5.0)
|
||||
raphael-rails (2.1.2)
|
||||
@@ -687,13 +694,12 @@ GEM
|
||||
rspec-retry (0.4.5)
|
||||
rspec-core
|
||||
rspec-support (3.3.0)
|
||||
rubocop (0.35.1)
|
||||
astrolabe (~> 1.3)
|
||||
parser (>= 2.2.3.0, < 3.0)
|
||||
rubocop (0.38.0)
|
||||
parser (>= 2.3.0.6, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
tins (<= 1.6.0)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-fogbugz (0.2.1)
|
||||
crack (~> 0.4)
|
||||
ruby-progressbar (1.7.5)
|
||||
@@ -843,6 +849,7 @@ GEM
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.1)
|
||||
unicode-display_width (1.0.2)
|
||||
unicorn (4.9.0)
|
||||
kgio (~> 2.6)
|
||||
rack
|
||||
@@ -992,6 +999,7 @@ DEPENDENCIES
|
||||
paranoia (~> 2.0)
|
||||
pg (~> 0.18.2)
|
||||
poltergeist (~> 1.9.0)
|
||||
premailer-rails (~> 1.9.0)
|
||||
pry-rails
|
||||
quiet_assets (~> 1.0.2)
|
||||
rack-attack (~> 4.3.1)
|
||||
@@ -1013,7 +1021,7 @@ DEPENDENCIES
|
||||
rqrcode-rails3 (~> 0.1.7)
|
||||
rspec-rails (~> 3.3.0)
|
||||
rspec-retry
|
||||
rubocop (~> 0.35.0)
|
||||
rubocop (~> 0.38.0)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
sanitize (~> 2.0)
|
||||
sass-rails (~> 5.0.0)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#= require jquery
|
||||
#= require jquery-ui/autocomplete
|
||||
#= require jquery-ui/datepicker
|
||||
#= require jquery-ui/draggable
|
||||
#= require jquery-ui/effect-highlight
|
||||
#= require jquery-ui/sortable
|
||||
#= require jquery_ujs
|
||||
@@ -138,7 +139,7 @@ $ ->
|
||||
|
||||
# Initialize tooltips
|
||||
$('body').tooltip(
|
||||
selector: '.has_tooltip, [data-toggle="tooltip"]'
|
||||
selector: '.has-tooltip, [data-toggle="tooltip"]'
|
||||
placement: (_, el) ->
|
||||
$el = $(el)
|
||||
$el.data('placement') || 'bottom'
|
||||
|
||||
@@ -5,7 +5,6 @@ class @Aside
|
||||
e.preventDefault()
|
||||
btn = $(e.currentTarget)
|
||||
icon = btn.find('i')
|
||||
console.log('1')
|
||||
|
||||
if icon.hasClass('fa-angle-left')
|
||||
btn.parent().find('section').hide()
|
||||
|
||||
@@ -122,7 +122,7 @@ class @AwardsHandler
|
||||
|
||||
nodes = []
|
||||
nodes.push(
|
||||
"<button class='btn award-control js-emoji-btn has_tooltip active' title='me'>",
|
||||
"<button class='btn award-control js-emoji-btn has-tooltip active' title='me'>",
|
||||
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
|
||||
"<span class='award-control-text js-counter'>1</span>",
|
||||
"</button>"
|
||||
|
||||
@@ -167,7 +167,11 @@ class GitLabDropdown
|
||||
|
||||
hidden: =>
|
||||
if @options.filterable
|
||||
@dropdown.find(".dropdown-input-field").blur().val("")
|
||||
@dropdown
|
||||
.find(".dropdown-input-field")
|
||||
.blur()
|
||||
.val("")
|
||||
.trigger("keyup")
|
||||
|
||||
if @dropdown.find(".dropdown-toggle-page").length
|
||||
$('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
class @IssuableForm
|
||||
issueMoveConfirmMsg: 'Are you sure you want to move this issue to another project?'
|
||||
wipRegex: /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i
|
||||
|
||||
constructor: (@form) ->
|
||||
GitLab.GfmAutoComplete.setup()
|
||||
new UsersSelect()
|
||||
@@ -7,12 +9,13 @@ class @IssuableForm
|
||||
|
||||
@titleField = @form.find("input[name*='[title]']")
|
||||
@descriptionField = @form.find("textarea[name*='[description]']")
|
||||
@issueMoveField = @form.find("#move_to_project_id")
|
||||
|
||||
return unless @titleField.length && @descriptionField.length
|
||||
|
||||
@initAutosave()
|
||||
|
||||
@form.on "submit", @resetAutosave
|
||||
@form.on "submit", @handleSubmit
|
||||
@form.on "click", ".btn-cancel", @resetAutosave
|
||||
|
||||
@initWip()
|
||||
@@ -30,6 +33,12 @@ class @IssuableForm
|
||||
"description"
|
||||
]
|
||||
|
||||
handleSubmit: =>
|
||||
if (parseInt(@issueMoveField?.val()) ? 0) > 0
|
||||
return false unless confirm(@issueMoveConfirmMsg)
|
||||
|
||||
@resetAutosave()
|
||||
|
||||
resetAutosave: =>
|
||||
@titleField.data("autosave").reset()
|
||||
@descriptionField.data("autosave").reset()
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# Handles persisting and restoring the current tab selection and lazily-loading
|
||||
# content on the MergeRequests#show page.
|
||||
#
|
||||
#= require jquery.cookie
|
||||
#
|
||||
# ### Example Markup
|
||||
#
|
||||
# <ul class="nav-links merge-request-tabs">
|
||||
@@ -68,11 +70,15 @@ class @MergeRequestTabs
|
||||
|
||||
if action == 'commits'
|
||||
@loadCommits($target.attr('href'))
|
||||
@expandView()
|
||||
else if action == 'diffs'
|
||||
@loadDiff($target.attr('href'))
|
||||
@shrinkView()
|
||||
else if action == 'builds'
|
||||
@loadBuilds($target.attr('href'))
|
||||
@expandView()
|
||||
else
|
||||
@expandView()
|
||||
|
||||
@setCurrentAction(action)
|
||||
|
||||
@@ -189,11 +195,24 @@ class @MergeRequestTabs
|
||||
$('.container-fluid').removeClass('container-limited')
|
||||
|
||||
shrinkView: ->
|
||||
$gutterIcon = $('.js-sidebar-toggle i')
|
||||
$gutterIcon = $('.js-sidebar-toggle i:visible')
|
||||
|
||||
# Wait until listeners are set
|
||||
setTimeout( ->
|
||||
# Only when sidebar is expanded
|
||||
if $gutterIcon.is('.fa-angle-double-right')
|
||||
$gutterIcon.closest('a').trigger('click', [true])
|
||||
, 0)
|
||||
|
||||
# Expand the issuable sidebar unless the user explicitly collapsed it
|
||||
expandView: ->
|
||||
return if $.cookie('collapsed_gutter') == 'true'
|
||||
|
||||
$gutterIcon = $('.js-sidebar-toggle i:visible')
|
||||
|
||||
# Wait until listeners are set
|
||||
setTimeout( ->
|
||||
# Only when sidebar is collapsed
|
||||
if $gutterIcon.is('.fa-angle-double-right')
|
||||
$gutterIcon.closest('a').trigger('click',[true])
|
||||
if $gutterIcon.is('.fa-angle-double-left')
|
||||
$gutterIcon.closest('a').trigger('click', [true])
|
||||
, 0)
|
||||
|
||||
@@ -361,14 +361,12 @@ class @Notes
|
||||
showEditForm: (e) ->
|
||||
e.preventDefault()
|
||||
note = $(this).closest(".note")
|
||||
note.find(".note-body > .note-text").hide()
|
||||
note.find(".note-header").hide()
|
||||
note.addClass "is-editting"
|
||||
form = note.find(".note-edit-form")
|
||||
isNewForm = form.is(':not(.gfm-form)')
|
||||
if isNewForm
|
||||
form.addClass('gfm-form')
|
||||
form.addClass('current-note-edit-form')
|
||||
form.show()
|
||||
|
||||
# Show the attachment delete link
|
||||
note.find(".js-note-attachment-delete").show()
|
||||
@@ -402,11 +400,9 @@ class @Notes
|
||||
cancelEdit: (e) ->
|
||||
e.preventDefault()
|
||||
note = $(this).closest(".note")
|
||||
note.find(".note-body > .note-text").show()
|
||||
note.find(".note-header").show()
|
||||
note.removeClass "is-editting"
|
||||
note.find(".current-note-edit-form")
|
||||
.removeClass("current-note-edit-form")
|
||||
.hide()
|
||||
|
||||
###
|
||||
Called in response to deleting a note of any kind.
|
||||
|
||||
@@ -11,7 +11,6 @@ class @Project
|
||||
$(@).toggleClass('active')
|
||||
|
||||
url = $("#project_clone").val()
|
||||
console.log("url",url)
|
||||
|
||||
# Update the input field
|
||||
$('#project_clone').val(url)
|
||||
|
||||
@@ -95,4 +95,4 @@ window.ContributorsStatGraphUtil =
|
||||
if date_range is null || date_range[0] <= new Date(date) <= date_range[1]
|
||||
true
|
||||
else
|
||||
false
|
||||
false
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
&.group-avatar, &.project-avatar, &.avatar-tile {
|
||||
@include border-radius(0px);
|
||||
@include border-radius(0);
|
||||
}
|
||||
|
||||
&.s16 { width: 16px; height: 16px; margin-right: 6px; }
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
margin: 0;
|
||||
font-size: 23px;
|
||||
font-weight: normal;
|
||||
margin: 16px 0 5px 0;
|
||||
margin: 16px 0 5px;
|
||||
color: #4c4e54;
|
||||
font-size: 23px;
|
||||
line-height: 1.1;
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
width: 240px;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 0;
|
||||
padding: 10px 10px;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
background-color: $dropdown-bg;
|
||||
|
||||
@@ -117,4 +117,4 @@ body {
|
||||
&.ui_violet {
|
||||
@include gitlab-theme(#98c, $theme-violet, #436, #325);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ body {
|
||||
}
|
||||
|
||||
.container .content {
|
||||
margin: 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.navless-container {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Generic mixins
|
||||
*/
|
||||
@mixin box-shadow($shadow) {
|
||||
@mixin box-shadow($shadow) {
|
||||
-webkit-box-shadow: $shadow;
|
||||
-moz-box-shadow: $shadow;
|
||||
-ms-box-shadow: $shadow;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
|
||||
.select2-drop {
|
||||
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
|
||||
@include box-shadow(rgba(76, 86, 103, 0.247059) 0 0 1px 0, rgba(31, 37, 50, 0.317647) 0 2px 18px 0);
|
||||
@include border-radius ($border-radius-default);
|
||||
border: none;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
h1 {
|
||||
font-size: 1.3em;
|
||||
font-weight: 600;
|
||||
margin: 24px 0 12px 0;
|
||||
padding: 0 0 10px 0;
|
||||
margin: 24px 0 12px;
|
||||
padding: 0 0 10px;
|
||||
border-bottom: 1px solid #e7e9ed;
|
||||
color: #313236;
|
||||
}
|
||||
@@ -48,27 +48,27 @@
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: 600;
|
||||
margin: 24px 0 12px 0;
|
||||
margin: 24px 0 12px;
|
||||
color: #313236;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 24px 0 12px 0;
|
||||
margin: 24px 0 12px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 24px 0 12px 0;
|
||||
margin: 24px 0 12px;
|
||||
font-size: 0.98em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 24px 0 12px 0;
|
||||
margin: 24px 0 12px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin: 24px 0 12px 0;
|
||||
margin: 24px 0 12px;
|
||||
font-size: 0.90em;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
color: #7f8fa4;
|
||||
font-size: inherit;
|
||||
padding: 8px 21px;
|
||||
margin: 12px 0 12px;
|
||||
margin: 12px 0;
|
||||
border-left: 3px solid #e7e9ed;
|
||||
}
|
||||
|
||||
@@ -88,13 +88,13 @@
|
||||
|
||||
p {
|
||||
color: #5c5d5e;
|
||||
margin: 6px 0 0 0;
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
margin: 12px 0 12px 0;
|
||||
margin: 12px 0;
|
||||
color: #5c5d5e;
|
||||
th {
|
||||
background: #f8fafc;
|
||||
@@ -102,7 +102,7 @@
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 12px 0 12px 0;
|
||||
margin: 12px 0;
|
||||
font-size: 13px;
|
||||
line-height: 1.6em;
|
||||
overflow-x: auto;
|
||||
@@ -191,7 +191,7 @@ body {
|
||||
line-height: 1.3;
|
||||
font-size: 1.25em;
|
||||
font-weight: 600;
|
||||
margin: 12px 7px 12px 7px;
|
||||
margin: 12px 7px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
p.details {
|
||||
font-style:italic;
|
||||
color:#777
|
||||
}
|
||||
.footer p {
|
||||
font-size:small;
|
||||
color:#777
|
||||
}
|
||||
pre.commit-message {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.file-stats a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.file-stats .new-file {
|
||||
color: #090;
|
||||
}
|
||||
.file-stats .deleted-file {
|
||||
color: #B00;
|
||||
}
|
||||
@@ -34,9 +34,9 @@
|
||||
background: #fff
|
||||
}
|
||||
|
||||
.visibility-levels {
|
||||
.controls {
|
||||
margin-bottom: 9px;
|
||||
.visibility-levels {
|
||||
.controls {
|
||||
margin-bottom: 9px;
|
||||
}
|
||||
|
||||
i {
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
}
|
||||
.image-info {
|
||||
font-size: 12px;
|
||||
margin: 5px 0 0 0;
|
||||
margin: 5px 0 0;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
.block {
|
||||
width: $sidebar_collapsed_width - 1px;
|
||||
margin-left: -19px;
|
||||
padding: 15px 0 0 0;
|
||||
padding: 15px 0 0;
|
||||
border-bottom: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -273,12 +273,12 @@
|
||||
}
|
||||
|
||||
.participants-list {
|
||||
margin: -5px -5px;
|
||||
margin: -5px;
|
||||
}
|
||||
|
||||
.participants-author {
|
||||
display: inline-block;
|
||||
padding: 5px 5px;
|
||||
padding: 5px;
|
||||
|
||||
.author_link {
|
||||
display: block;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
.login-heading h3 {
|
||||
font-weight: 300;
|
||||
line-height: 1.5;
|
||||
margin: 0 0 10px 0;
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.new_note, .edit_note {
|
||||
.new_note, .note-edit-form {
|
||||
.note-form-actions {
|
||||
margin-top: $gl-padding;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,18 @@ ul.notes {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
&.is-editting {
|
||||
.note-header,
|
||||
.note-text,
|
||||
.edited-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.note-edit-form {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.note-body {
|
||||
overflow: auto;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
|
||||
.account-well {
|
||||
padding: 10px 10px;
|
||||
padding: 10px;
|
||||
background-color: $help-well-bg;
|
||||
border: 1px solid $help-well-border;
|
||||
border-radius: $border-radius-base;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
.dropdown-menu {
|
||||
left: auto;
|
||||
width: auto;
|
||||
right: 0px;
|
||||
right: 0;
|
||||
max-width: 240px;
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ pre.light-well {
|
||||
}
|
||||
|
||||
.git-empty {
|
||||
margin: 0 7px 0 7px;
|
||||
margin: 0 7px;
|
||||
|
||||
h5 {
|
||||
color: #5c5d5e;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#contributors {
|
||||
.contributors-list {
|
||||
margin: 0 0 10px 0;
|
||||
margin: 0 0 10px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -21,19 +21,19 @@
|
||||
$l-white: #fff;
|
||||
|
||||
.term-bold {
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
.term-italic {
|
||||
font-style: italic;
|
||||
font-style: italic;
|
||||
}
|
||||
.term-conceal {
|
||||
visibility: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.term-underline {
|
||||
text-decoration: underline;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.term-cross {
|
||||
text-decoration: line-through;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.term-fg-black {
|
||||
|
||||
@@ -5,12 +5,12 @@ class Admin::GroupsController < Admin::ApplicationController
|
||||
@groups = Group.all
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.search(params[:name]) if params[:name].present?
|
||||
@groups = @groups.page(params[:page]).per(PER_PAGE)
|
||||
@groups = @groups.page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page]).per(PER_PAGE)
|
||||
@projects = @group.projects.page(params[:projects_page]).per(PER_PAGE)
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page])
|
||||
@projects = @group.projects.page(params[:projects_page])
|
||||
end
|
||||
|
||||
def new
|
||||
|
||||
@@ -2,7 +2,7 @@ class Admin::LabelsController < Admin::ApplicationController
|
||||
before_action :set_label, only: [:show, :edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
@labels = Label.templates.page(params[:page]).per(PER_PAGE)
|
||||
@labels = Label.templates.page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -11,15 +11,15 @@ class Admin::ProjectsController < Admin::ApplicationController
|
||||
@projects = @projects.non_archived unless params[:with_archived].present?
|
||||
@projects = @projects.search(params[:name]) if params[:name].present?
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
if @group
|
||||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page]).per(PER_PAGE)
|
||||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page])
|
||||
end
|
||||
|
||||
@project_members = @project.project_members.page(params[:project_members_page]).per(PER_PAGE)
|
||||
@project_members = @project.project_members.page(params[:project_members_page])
|
||||
end
|
||||
|
||||
def transfer
|
||||
|
||||
@@ -6,8 +6,6 @@ class ApplicationController < ActionController::Base
|
||||
include GitlabRoutingHelper
|
||||
include PageLayoutHelper
|
||||
|
||||
PER_PAGE = 20
|
||||
|
||||
before_action :authenticate_user_from_token!
|
||||
before_action :authenticate_user!
|
||||
before_action :validate_user_service_ticket!
|
||||
|
||||
@@ -7,7 +7,7 @@ class AutocompleteController < ApplicationController
|
||||
@users = @users.search(params[:search]) if params[:search].present?
|
||||
@users = @users.active
|
||||
@users = @users.reorder(:name)
|
||||
@users = @users.page(params[:page]).per(PER_PAGE)
|
||||
@users = @users.page(params[:page])
|
||||
|
||||
if params[:search].blank?
|
||||
# Include current user if available to filter by "Me"
|
||||
|
||||
@@ -6,7 +6,7 @@ module GlobalMilestones
|
||||
@milestones = MilestonesFinder.new.execute(@projects, params)
|
||||
@milestones = GlobalMilestone.build_collection(@milestones)
|
||||
@milestones = @milestones.sort_by { |x| x.due_date.nil? ? epoch : x.due_date }
|
||||
@milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
@milestones = Kaminari.paginate_array(@milestones).page(params[:page])
|
||||
end
|
||||
|
||||
def milestone
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
module IssuableActions
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_action :authorize_destroy_issuable!, only: :destroy
|
||||
end
|
||||
|
||||
def destroy
|
||||
issuable.destroy
|
||||
|
||||
name = issuable.class.name.titleize.downcase
|
||||
flash[:notice] = "The #{name} was successfully deleted."
|
||||
redirect_to polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable.class])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authorize_destroy_issuable!
|
||||
unless current_user.can?(:"destroy_#{issuable.to_ability_name}", issuable)
|
||||
return access_denied!
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,7 @@ module IssuesAction
|
||||
|
||||
def issues
|
||||
@issues = get_issues_collection.non_archived
|
||||
@issues = @issues.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
@issues = @issues.page(params[:page])
|
||||
@issues = @issues.preload(:author, :project)
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
|
||||
@@ -3,7 +3,7 @@ module MergeRequestsAction
|
||||
|
||||
def merge_requests
|
||||
@merge_requests = get_merge_requests_collection.non_archived
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(ApplicationController::PER_PAGE)
|
||||
@merge_requests = @merge_requests.page(params[:page])
|
||||
@merge_requests = @merge_requests.preload(:author, :target_project)
|
||||
|
||||
@label = @issuable_finder.labels.first
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Dashboard::GroupsController < Dashboard::ApplicationController
|
||||
def index
|
||||
@group_members = current_user.group_members.page(params[:page]).per(PER_PAGE)
|
||||
@group_members = current_user.group_members.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.includes(:namespace)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.page(params[:page])
|
||||
|
||||
@last_push = current_user.recent_push
|
||||
|
||||
@@ -32,7 +32,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.includes(:namespace, :forked_from_project, :tags)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.page(params[:page])
|
||||
|
||||
@last_push = current_user.recent_push
|
||||
@groups = []
|
||||
|
||||
@@ -6,6 +6,6 @@ class Dashboard::SnippetsController < Dashboard::ApplicationController
|
||||
user: current_user,
|
||||
scope: params[:scope]
|
||||
)
|
||||
@snippets = @snippets.page(params[:page]).per(PER_PAGE)
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController
|
||||
before_action :find_todos, only: [:index, :destroy, :destroy_all]
|
||||
|
||||
def index
|
||||
@todos = @todos.page(params[:page]).per(PER_PAGE)
|
||||
@todos = @todos.page(params[:page])
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
||||
@@ -3,6 +3,6 @@ class Explore::GroupsController < Explore::ApplicationController
|
||||
@groups = GroupsFinder.new.execute(current_user)
|
||||
@groups = @groups.search(params[:search]) if params[:search].present?
|
||||
@groups = @groups.sort(@sort = params[:sort])
|
||||
@groups = @groups.page(params[:page]).per(PER_PAGE)
|
||||
@groups = @groups.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Explore::ProjectsController < Explore::ApplicationController
|
||||
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.includes(:namespace).page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
@@ -23,7 +23,7 @@ class Explore::ProjectsController < Explore::ApplicationController
|
||||
def trending
|
||||
@projects = TrendingProjectsFinder.new.execute(current_user)
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
@@ -39,7 +39,7 @@ class Explore::ProjectsController < Explore::ApplicationController
|
||||
@projects = ProjectsFinder.new.execute(current_user)
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.reorder('star_count DESC')
|
||||
@projects = @projects.page(params[:page]).per(PER_PAGE)
|
||||
@projects = @projects.page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Explore::SnippetsController < Explore::ApplicationController
|
||||
def index
|
||||
@snippets = SnippetsFinder.new.execute(current_user, filter: :all)
|
||||
@snippets = @snippets.page(params[:page]).per(PER_PAGE)
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ class GroupsController < Groups::ApplicationController
|
||||
@projects = @projects.includes(:namespace)
|
||||
@projects = filter_projects(@projects)
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
|
||||
@projects = @projects.page(params[:page]) if params[:filter_projects].blank?
|
||||
|
||||
@shared_projects = GroupProjectsFinder.new(group, only_shared: true).execute(current_user)
|
||||
|
||||
|
||||
@@ -34,8 +34,7 @@ class ProfilesController < Profiles::ApplicationController
|
||||
def audit_log
|
||||
@events = AuditEvent.where(entity_type: "User", entity_id: current_user.id).
|
||||
order("created_at DESC").
|
||||
page(params[:page]).
|
||||
per(PER_PAGE)
|
||||
page(params[:page])
|
||||
end
|
||||
|
||||
def update_username
|
||||
|
||||
@@ -8,7 +8,7 @@ class Projects::BranchesController < Projects::ApplicationController
|
||||
def index
|
||||
@sort = params[:sort] || 'name'
|
||||
@branches = @repository.branches_sorted_by(@sort)
|
||||
@branches = Kaminari.paginate_array(@branches).page(params[:page]).per(PER_PAGE)
|
||||
@branches = Kaminari.paginate_array(@branches).page(params[:page])
|
||||
|
||||
@max_commits = @branches.reduce(0) do |memo, branch|
|
||||
diverging_commit_counts = repository.diverging_commit_counts(branch)
|
||||
|
||||
@@ -15,7 +15,7 @@ class Projects::ForksController < Projects::ApplicationController
|
||||
|
||||
@sort = params[:sort] || 'id_desc'
|
||||
@forks = @forks.search(params[:filter_projects]) if params[:filter_projects].present?
|
||||
@forks = @forks.order_by(@sort).page(params[:page]).per(PER_PAGE)
|
||||
@forks = @forks.order_by(@sort).page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class Projects::IssuesController < Projects::ApplicationController
|
||||
include ToggleSubscriptionAction
|
||||
include IssuableActions
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :issue, only: [:edit, :update, :show]
|
||||
@@ -33,7 +34,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
@issues = @issues.page(params[:page]).per(PER_PAGE)
|
||||
@issues = @issues.page(params[:page])
|
||||
@label = @project.labels.find_by(title: params[:label_name])
|
||||
|
||||
respond_to do |format|
|
||||
@@ -90,6 +91,12 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||
def update
|
||||
@issue = Issues::UpdateService.new(project, current_user, issue_params).execute(issue)
|
||||
|
||||
if params[:move_to_project_id].to_i > 0
|
||||
new_project = Project.find(params[:move_to_project_id])
|
||||
move_service = Issues::MoveService.new(project, current_user)
|
||||
@issue = move_service.execute(@issue, new_project)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html do
|
||||
@@ -127,6 +134,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
||||
end
|
||||
end
|
||||
alias_method :subscribable_resource, :issue
|
||||
alias_method :issuable, :issue
|
||||
|
||||
def authorize_read_issue!
|
||||
return render_404 unless can?(current_user, :read_issue, @issue)
|
||||
|
||||
@@ -11,7 +11,7 @@ class Projects::LabelsController < Projects::ApplicationController
|
||||
respond_to :js, :html
|
||||
|
||||
def index
|
||||
@labels = @project.labels.page(params[:page]).per(PER_PAGE)
|
||||
@labels = @project.labels.page(params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
include ToggleSubscriptionAction
|
||||
include DiffHelper
|
||||
include IssuableActions
|
||||
|
||||
before_action :module_enabled
|
||||
before_action :merge_request, only: [
|
||||
@@ -34,7 +35,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
|
||||
@merge_requests = @merge_requests.page(params[:page])
|
||||
@merge_requests = @merge_requests.preload(:target_project)
|
||||
|
||||
@label = @project.labels.find_by(title: params[:label_name])
|
||||
@@ -255,6 +256,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
||||
@merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
|
||||
end
|
||||
alias_method :subscribable_resource, :merge_request
|
||||
alias_method :issuable, :merge_request
|
||||
|
||||
def closes_issues
|
||||
@closes_issues ||= @merge_request.closes_issues
|
||||
|
||||
@@ -22,7 +22,7 @@ class Projects::MilestonesController < Projects::ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@milestones = @milestones.page(params[:page]).per(PER_PAGE)
|
||||
@milestones = @milestones.page(params[:page])
|
||||
end
|
||||
format.json do
|
||||
render json: @milestones
|
||||
|
||||
@@ -21,7 +21,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
||||
filter: :by_project,
|
||||
project: @project
|
||||
})
|
||||
@snippets = @snippets.page(params[:page]).per(PER_PAGE)
|
||||
@snippets = @snippets.page(params[:page])
|
||||
end
|
||||
|
||||
def new
|
||||
|
||||
@@ -7,7 +7,7 @@ class Projects::TagsController < Projects::ApplicationController
|
||||
|
||||
def index
|
||||
sorted = VersionSorter.rsort(@repository.tag_names)
|
||||
@tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE)
|
||||
@tags = Kaminari.paginate_array(sorted).page(params[:page])
|
||||
@releases = project.releases.where(tag: @tags)
|
||||
end
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ class Projects::WikisController < Projects::ApplicationController
|
||||
before_action :load_project_wiki
|
||||
|
||||
def pages
|
||||
@wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page]).per(PER_PAGE)
|
||||
@wiki_pages = Kaminari.paginate_array(@project_wiki.pages).page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -25,7 +25,7 @@ class SnippetsController < ApplicationController
|
||||
filter: :by_user,
|
||||
user: @user,
|
||||
scope: params[:scope] }).
|
||||
page(params[:page]).per(PER_PAGE)
|
||||
page(params[:page])
|
||||
|
||||
render 'index'
|
||||
else
|
||||
|
||||
@@ -100,7 +100,7 @@ class UsersController < ApplicationController
|
||||
def load_projects
|
||||
@projects =
|
||||
PersonalProjectsFinder.new(@user).execute(current_user)
|
||||
.page(params[:page]).per(PER_PAGE)
|
||||
.page(params[:page])
|
||||
end
|
||||
|
||||
def load_contributed_projects
|
||||
|
||||
@@ -27,7 +27,7 @@ module BlobHelper
|
||||
link_opts)
|
||||
|
||||
if !on_top_of_branch?(project, ref)
|
||||
button_tag "Edit", class: "btn btn-default disabled has_tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
|
||||
button_tag "Edit", class: "btn btn-default disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' }
|
||||
elsif can_edit_blob?(blob, project, ref)
|
||||
link_to "Edit", edit_path, class: 'btn'
|
||||
elsif can?(current_user, :fork_project, project)
|
||||
@@ -50,9 +50,9 @@ module BlobHelper
|
||||
return unless blob
|
||||
|
||||
if !on_top_of_branch?(project, ref)
|
||||
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
|
||||
button_tag label, class: "btn btn-#{btn_class} disabled has-tooltip", title: "You can only #{action} files when you are on a branch", data: { container: 'body' }
|
||||
elsif blob.lfs_pointer?
|
||||
button_tag label, class: "btn btn-#{btn_class} disabled has_tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
|
||||
button_tag label, class: "btn btn-#{btn_class} disabled has-tooltip", title: "It is not possible to #{action} files that are stored in LFS using the web interface", data: { container: 'body' }
|
||||
elsif can_edit_blob?(blob, project, ref)
|
||||
button_tag label, class: "btn btn-#{btn_class}", 'data-target' => "#modal-#{modal_type}-blob", 'data-toggle' => 'modal'
|
||||
elsif can?(current_user, :fork_project, project)
|
||||
|
||||
@@ -23,36 +23,34 @@ module ButtonHelper
|
||||
end
|
||||
|
||||
def http_clone_button(project)
|
||||
klass = 'btn js-protocol-switch'
|
||||
klass << ' active' if default_clone_protocol == 'http'
|
||||
klass << ' has_tooltip' if current_user.try(:require_password?)
|
||||
klass = 'http-selector'
|
||||
klass << ' has-tooltip' if current_user.try(:require_password?)
|
||||
|
||||
protocol = gitlab_config.protocol.upcase
|
||||
|
||||
content_tag :button, protocol,
|
||||
content_tag :a, protocol,
|
||||
class: klass,
|
||||
href: @project.http_url_to_repo,
|
||||
data: {
|
||||
clone: project.http_url_to_repo,
|
||||
html: true,
|
||||
placement: 'right',
|
||||
container: 'body',
|
||||
html: 'true',
|
||||
title: "Set a password on your account<br>to pull or push via #{protocol}"
|
||||
},
|
||||
type: :button
|
||||
}
|
||||
end
|
||||
|
||||
def ssh_clone_button(project)
|
||||
klass = 'btn js-protocol-switch'
|
||||
klass << ' active' if default_clone_protocol == 'ssh'
|
||||
klass << ' has_tooltip' if current_user.try(:require_ssh_key?)
|
||||
klass = 'ssh-selector'
|
||||
klass << ' has-tooltip' if current_user.try(:require_ssh_key?)
|
||||
|
||||
content_tag :button, 'SSH',
|
||||
content_tag :a, 'SSH',
|
||||
class: klass,
|
||||
href: project.ssh_url_to_repo,
|
||||
data: {
|
||||
clone: project.ssh_url_to_repo,
|
||||
html: true,
|
||||
placement: 'right',
|
||||
container: 'body',
|
||||
html: 'true',
|
||||
title: 'Add an SSH key to your profile<br>to pull or push via SSH.'
|
||||
},
|
||||
type: :button
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -182,7 +182,7 @@ module CommitsHelper
|
||||
end
|
||||
|
||||
options = {
|
||||
class: "commit-#{options[:source]}-link has_tooltip",
|
||||
class: "commit-#{options[:source]}-link has-tooltip",
|
||||
data: { 'original-title'.to_sym => sanitize(source_email) }
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,19 @@ module IssuesHelper
|
||||
options_from_collection_for_select(milestones, 'id', 'title', object.milestone_id)
|
||||
end
|
||||
|
||||
def project_options(issuable, current_user, ability: :read_project)
|
||||
projects = current_user.authorized_projects
|
||||
projects = projects.select do |project|
|
||||
current_user.can?(ability, project)
|
||||
end
|
||||
|
||||
no_project = OpenStruct.new(id: 0, name_with_namespace: 'No project')
|
||||
projects.unshift(no_project)
|
||||
projects.delete(issuable.project)
|
||||
|
||||
options_from_collection_for_select(projects, :id, :name_with_namespace)
|
||||
end
|
||||
|
||||
def status_box_class(item)
|
||||
if item.respond_to?(:expired?) && item.expired?
|
||||
'status-box-expired'
|
||||
|
||||
@@ -56,7 +56,7 @@ module LabelsHelper
|
||||
|
||||
# Intentionally not using content_tag here so that this method can be called
|
||||
# by LabelReferenceFilter
|
||||
span = %(<span class="label color-label #{"has_tooltip" if tooltip}" ) +
|
||||
span = %(<span class="label color-label #{"has-tooltip" if tooltip}" ) +
|
||||
%(style="background-color: #{label_color}; color: #{text_color}" ) +
|
||||
%(title="#{escape_once(label.description)}" data-container="body">) +
|
||||
%(#{escape_once(label.name)}#{label_suffix}</span>)
|
||||
|
||||
@@ -52,7 +52,7 @@ module ProjectsHelper
|
||||
link_to(author_html, user_path(author), class: "author_link #{"#{opts[:mobile_classes]}" if opts[:mobile_classes]}").html_safe
|
||||
else
|
||||
title = opts[:title].sub(":name", sanitize(author.name))
|
||||
link_to(author_html, user_path(author), class: "author_link has_tooltip", data: { 'original-title'.to_sym => title, container: 'body' } ).html_safe
|
||||
link_to(author_html, user_path(author), class: "author_link has-tooltip", data: { 'original-title'.to_sym => title, container: 'body' } ).html_safe
|
||||
end
|
||||
end
|
||||
|
||||
@@ -209,7 +209,7 @@ module ProjectsHelper
|
||||
|
||||
def default_clone_protocol
|
||||
if !current_user || current_user.require_ssh_key?
|
||||
"http"
|
||||
gitlab_config.protocol
|
||||
else
|
||||
"ssh"
|
||||
end
|
||||
|
||||
@@ -36,6 +36,14 @@ module Emails
|
||||
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
|
||||
end
|
||||
|
||||
def issue_moved_email(recipient, issue, new_issue, updated_by_user)
|
||||
setup_issue_mail(issue.id, recipient.id)
|
||||
|
||||
@new_issue = new_issue
|
||||
@new_project = new_issue.project
|
||||
mail_answer_thread(issue, issue_thread_options(updated_by_user.id, recipient.id))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setup_issue_mail(issue_id, recipient_id)
|
||||
|
||||
@@ -234,7 +234,9 @@ class Ability
|
||||
:rename_project,
|
||||
:remove_project,
|
||||
:archive_project,
|
||||
:remove_fork_project
|
||||
:remove_fork_project,
|
||||
:destroy_merge_request,
|
||||
:destroy_issue
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ module InternalId
|
||||
end
|
||||
|
||||
def set_iid
|
||||
max_iid = project.send(self.class.name.tableize).maximum(:iid)
|
||||
records = project.send(self.class.name.tableize)
|
||||
records = records.with_deleted if self.paranoid?
|
||||
max_iid = records.maximum(:iid)
|
||||
|
||||
self.iid = max_iid.to_i + 1
|
||||
end
|
||||
|
||||
|
||||
@@ -58,6 +58,8 @@ module Issuable
|
||||
attr_mentionable :description, cache: true
|
||||
participant :author, :assignee, :notes_with_associations
|
||||
strip_attributes :title
|
||||
|
||||
acts_as_paranoid
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
@@ -209,4 +211,13 @@ module Issuable
|
||||
Taskable.get_updated_tasks(old_content: previous_changes['description'].first,
|
||||
new_content: description)
|
||||
end
|
||||
|
||||
##
|
||||
# Method that checks if issuable can be moved to another project.
|
||||
#
|
||||
# Should be overridden if issuable can be moved.
|
||||
#
|
||||
def can_move?(*)
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
+18
-3
@@ -16,6 +16,7 @@
|
||||
# state :string(255)
|
||||
# iid :integer
|
||||
# updated_by_id :integer
|
||||
# moved_to_id :integer
|
||||
#
|
||||
|
||||
require 'carrierwave/orm/activerecord'
|
||||
@@ -31,6 +32,8 @@ class Issue < ActiveRecord::Base
|
||||
ActsAsTaggableOn.strict_case_match = true
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :moved_to, class_name: 'Issue'
|
||||
|
||||
validates :project, presence: true
|
||||
|
||||
scope :cared, ->(user) { where(assignee_id: user) }
|
||||
@@ -102,9 +105,9 @@ class Issue < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def related_branches
|
||||
return [] if self.project.empty_repo?
|
||||
|
||||
self.project.repository.branch_names.select { |branch| branch.end_with?("-#{iid}") }
|
||||
project.repository.branch_names.select do |branch|
|
||||
branch.end_with?("-#{iid}")
|
||||
end
|
||||
end
|
||||
|
||||
# Reset issue events cache
|
||||
@@ -134,6 +137,18 @@ class Issue < ActiveRecord::Base
|
||||
end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
|
||||
end
|
||||
|
||||
def moved?
|
||||
!moved_to.nil?
|
||||
end
|
||||
|
||||
def can_move?(user, to_project = nil)
|
||||
if to_project
|
||||
return false unless user.can?(:admin_issue, to_project)
|
||||
end
|
||||
|
||||
!moved? && user.can?(:admin_issue, self.project)
|
||||
end
|
||||
|
||||
def to_branch_name
|
||||
"#{title.parameterize}-#{iid}"
|
||||
end
|
||||
|
||||
@@ -431,6 +431,7 @@ class Project < ActiveRecord::Base
|
||||
def safe_import_url
|
||||
result = URI.parse(self.import_url)
|
||||
result.password = '*****' unless result.password.nil?
|
||||
result.user = '*****' unless result.user.nil? || result.user == "git" #tokens or other data may be saved as user
|
||||
result.to_s
|
||||
rescue
|
||||
self.import_url
|
||||
@@ -887,6 +888,7 @@ class Project < ActiveRecord::Base
|
||||
# Forked import is handled asynchronously
|
||||
unless forked?
|
||||
if gitlab_shell.add_repository(path_with_namespace)
|
||||
repository.after_create
|
||||
true
|
||||
else
|
||||
errors.add(:base, 'Failed to create repository via gitlab-shell')
|
||||
|
||||
@@ -123,23 +123,27 @@ class ProjectWiki
|
||||
end
|
||||
|
||||
def repository
|
||||
Repository.new(path_with_namespace, @project)
|
||||
@repository ||= Repository.new(path_with_namespace, @project)
|
||||
end
|
||||
|
||||
def default_branch
|
||||
wiki.class.default_ref
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_repo!
|
||||
if init_repo(path_with_namespace)
|
||||
Gollum::Wiki.new(path_to_repo)
|
||||
wiki = Gollum::Wiki.new(path_to_repo)
|
||||
else
|
||||
raise CouldNotCreateWikiError
|
||||
end
|
||||
|
||||
repository.after_create
|
||||
|
||||
wiki
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init_repo(path_with_namespace)
|
||||
gitlab_shell.add_repository(path_with_namespace)
|
||||
end
|
||||
|
||||
@@ -42,12 +42,15 @@ class Repository
|
||||
end
|
||||
|
||||
def exists?
|
||||
return false unless raw_repository
|
||||
return @exists unless @exists.nil?
|
||||
|
||||
raw_repository.rugged
|
||||
true
|
||||
rescue Gitlab::Git::Repository::NoRepository
|
||||
false
|
||||
@exists = cache.fetch(:exists?) do
|
||||
begin
|
||||
raw_repository && raw_repository.rugged ? true : false
|
||||
rescue Gitlab::Git::Repository::NoRepository
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def empty?
|
||||
@@ -320,12 +323,23 @@ class Repository
|
||||
@avatar = nil
|
||||
end
|
||||
|
||||
def expire_exists_cache
|
||||
cache.expire(:exists?)
|
||||
@exists = nil
|
||||
end
|
||||
|
||||
# Runs code after a repository has been created.
|
||||
def after_create
|
||||
expire_exists_cache
|
||||
end
|
||||
|
||||
# Runs code just before a repository is deleted.
|
||||
def before_delete
|
||||
expire_cache if exists?
|
||||
|
||||
expire_root_ref_cache
|
||||
expire_emptiness_caches
|
||||
expire_exists_cache
|
||||
end
|
||||
|
||||
# Runs code just before the HEAD of a repository is changed.
|
||||
@@ -351,6 +365,7 @@ class Repository
|
||||
# Runs code after a repository has been forked/imported.
|
||||
def after_import
|
||||
expire_emptiness_caches
|
||||
expire_exists_cache
|
||||
end
|
||||
|
||||
# Runs code after a new commit has been pushed.
|
||||
|
||||
+1
-1
@@ -435,7 +435,7 @@ class User < ActiveRecord::Base
|
||||
Group.where("namespaces.id IN (#{union.to_sql})")
|
||||
end
|
||||
|
||||
# Returns the groups a user is authorized to access.
|
||||
# Returns projects user is authorized to access.
|
||||
def authorized_projects
|
||||
Project.where("projects.id IN (#{projects_union.to_sql})")
|
||||
end
|
||||
|
||||
@@ -120,7 +120,7 @@ class GitPushService < BaseService
|
||||
closed_issues = commit.closes_issues(current_user)
|
||||
closed_issues.each do |issue|
|
||||
if can?(current_user, :update_issue, issue)
|
||||
Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit)
|
||||
Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit: commit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module Issues
|
||||
class CloseService < Issues::BaseService
|
||||
def execute(issue, commit = nil)
|
||||
def execute(issue, commit: nil, notifications: true, system_note: true)
|
||||
if project.jira_tracker? && project.jira_service.active
|
||||
project.jira_service.execute(commit, issue)
|
||||
todo_service.close_issue(issue, current_user)
|
||||
@@ -9,8 +9,8 @@ module Issues
|
||||
|
||||
if project.default_issues_tracker? && issue.close
|
||||
event_service.close_issue(issue, current_user)
|
||||
create_note(issue, commit)
|
||||
notification_service.close_issue(issue, current_user)
|
||||
create_note(issue, commit) if system_note
|
||||
notification_service.close_issue(issue, current_user) if notifications
|
||||
todo_service.close_issue(issue, current_user)
|
||||
execute_hooks(issue, 'close')
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ module Issues
|
||||
filter_params
|
||||
label_params = params[:label_ids]
|
||||
issue = project.issues.new(params.except(:label_ids))
|
||||
issue.author = current_user
|
||||
issue.author = params[:author] || current_user
|
||||
|
||||
if issue.save
|
||||
issue.update_attributes(label_ids: label_params)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
module Issues
|
||||
class MoveService < Issues::BaseService
|
||||
class MoveError < StandardError; end
|
||||
|
||||
def execute(issue, new_project)
|
||||
@old_issue = issue
|
||||
@old_project = @project
|
||||
@new_project = new_project
|
||||
|
||||
unless issue.can_move?(current_user, new_project)
|
||||
raise MoveError, 'Cannot move issue due to insufficient permissions!'
|
||||
end
|
||||
|
||||
if @project == new_project
|
||||
raise MoveError, 'Cannot move issue to project it originates from!'
|
||||
end
|
||||
|
||||
# Using transaction because of a high resources footprint
|
||||
# on rewriting notes (unfolding references)
|
||||
#
|
||||
ActiveRecord::Base.transaction do
|
||||
# New issue tasks
|
||||
#
|
||||
@new_issue = create_new_issue
|
||||
|
||||
rewrite_notes
|
||||
add_note_moved_from
|
||||
|
||||
# Old issue tasks
|
||||
#
|
||||
add_note_moved_to
|
||||
close_issue
|
||||
mark_as_moved
|
||||
end
|
||||
|
||||
notify_participants
|
||||
|
||||
@new_issue
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_new_issue
|
||||
new_params = { id: nil, iid: nil, label_ids: [], milestone: nil,
|
||||
project: @new_project, author: @old_issue.author,
|
||||
description: unfold_references(@old_issue.description) }
|
||||
|
||||
new_params = @old_issue.serializable_hash.merge(new_params)
|
||||
CreateService.new(@new_project, @current_user, new_params).execute
|
||||
end
|
||||
|
||||
def rewrite_notes
|
||||
@old_issue.notes.find_each do |note|
|
||||
new_note = note.dup
|
||||
new_params = { project: @new_project, noteable: @new_issue,
|
||||
note: unfold_references(new_note.note),
|
||||
created_at: note.created_at }
|
||||
|
||||
new_note.update(new_params)
|
||||
end
|
||||
end
|
||||
|
||||
def close_issue
|
||||
close_service = CloseService.new(@old_project, @current_user)
|
||||
close_service.execute(@old_issue, notifications: false, system_note: false)
|
||||
end
|
||||
|
||||
def add_note_moved_from
|
||||
SystemNoteService.noteable_moved(@new_issue, @new_project,
|
||||
@old_issue, @current_user,
|
||||
direction: :from)
|
||||
end
|
||||
|
||||
def add_note_moved_to
|
||||
SystemNoteService.noteable_moved(@old_issue, @old_project,
|
||||
@new_issue, @current_user,
|
||||
direction: :to)
|
||||
end
|
||||
|
||||
def unfold_references(content)
|
||||
rewriter = Gitlab::Gfm::ReferenceRewriter.new(content, @old_project,
|
||||
@current_user)
|
||||
rewriter.rewrite(@new_project)
|
||||
end
|
||||
|
||||
def notify_participants
|
||||
notification_service.issue_moved(@old_issue, @new_issue, @current_user)
|
||||
end
|
||||
|
||||
def mark_as_moved
|
||||
@old_issue.update(moved_to: @new_issue)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -22,7 +22,7 @@ module MergeRequests
|
||||
closed_issues = merge_request.closes_issues(current_user)
|
||||
closed_issues.each do |issue|
|
||||
if can?(current_user, :update_issue, issue)
|
||||
Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request)
|
||||
Issues::CloseService.new(project, current_user, {}).execute(issue, commit: merge_request)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -236,6 +236,16 @@ class NotificationService
|
||||
end
|
||||
end
|
||||
|
||||
def issue_moved(issue, new_issue, current_user)
|
||||
recipients = build_recipients(issue, issue.project, current_user)
|
||||
|
||||
recipients.map do |recipient|
|
||||
email = mailer.issue_moved_email(recipient, issue, new_issue, current_user)
|
||||
email.deliver_later
|
||||
email
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Get project users with WATCH notification level
|
||||
|
||||
@@ -411,4 +411,26 @@ class SystemNoteService
|
||||
body = "Marked the task **#{new_task.source}** as #{status_label}"
|
||||
create_note(noteable: noteable, project: project, author: author, note: body)
|
||||
end
|
||||
|
||||
# Called when noteable has been moved to another project
|
||||
#
|
||||
# direction - symbol, :to or :from
|
||||
# noteable - Noteable object
|
||||
# noteable_ref - Referenced noteable
|
||||
# author - User performing the move
|
||||
#
|
||||
# Example Note text:
|
||||
#
|
||||
# "Moved to some_namespace/project_new#11"
|
||||
#
|
||||
# Returns the created Note object
|
||||
def self.noteable_moved(noteable, project, noteable_ref, author, direction:)
|
||||
unless [:to, :from].include?(direction)
|
||||
raise ArgumentError, "Invalid direction `#{direction}`"
|
||||
end
|
||||
|
||||
cross_reference = noteable_ref.to_reference(project)
|
||||
body = "Moved #{direction} #{cross_reference}"
|
||||
create_note(noteable: noteable, project: project, author: author, note: body)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- submit_btn_css ||= 'btn btn-link btn-remove btn-sm'
|
||||
= form_tag admin_application_path(application) do
|
||||
%input{:name => "_method", :type => "hidden", :value => "delete"}/
|
||||
= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
|
||||
= submit_tag 'Destroy', onclick: "return confirm('Are you sure?')", class: submit_btn_css
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
%label{for: "remember_me"}
|
||||
= check_box_tag :remember_me, '1', false, id: 'remember_me'
|
||||
%span Remember me
|
||||
= button_tag "Sign in", class: "btn-save btn"
|
||||
= button_tag "Sign in", class: "btn-save btn"
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
|
||||
%hr
|
||||
|
||||
= render 'form', application: @application
|
||||
= render 'form', application: @application
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
%h3.page-title An error has occurred
|
||||
%main{:role => "main"}
|
||||
%pre= @pre_auth.error_response.body[:error_description]
|
||||
%pre= @pre_auth.error_response.body[:error_description]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
%h3.page-title Authorization code:
|
||||
%main{:role => "main"}
|
||||
%code#authorization_code= params[:code]
|
||||
%code#authorization_code= params[:code]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%ul.nav.nav-sidebar
|
||||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do
|
||||
= link_to dashboard_projects_path, title: 'Projects' do
|
||||
= icon('home fw')
|
||||
= icon('bookmark fw')
|
||||
%span
|
||||
Projects
|
||||
= nav_link(controller: :todos) do
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%ul.nav.nav-sidebar
|
||||
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
|
||||
= link_to explore_root_path, title: 'Projects' do
|
||||
= icon('home fw')
|
||||
= icon('bookmark fw')
|
||||
%span
|
||||
Projects
|
||||
= nav_link(controller: :groups) do
|
||||
|
||||
@@ -1,33 +1,9 @@
|
||||
%html{lang: "en"}
|
||||
%head
|
||||
%meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
|
||||
%title
|
||||
GitLab
|
||||
:css
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
p.details {
|
||||
font-style:italic;
|
||||
color:#777
|
||||
}
|
||||
.footer p {
|
||||
font-size:small;
|
||||
color:#777
|
||||
}
|
||||
pre.commit-message {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.file-stats a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.file-stats .new-file {
|
||||
color: #090;
|
||||
}
|
||||
.file-stats .deleted-file {
|
||||
color: #B00;
|
||||
}
|
||||
%title
|
||||
GitLab
|
||||
= stylesheet_link_tag 'notify'
|
||||
%body
|
||||
%div.content
|
||||
= yield
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
%p
|
||||
Issue was moved to another project.
|
||||
%p
|
||||
New issue:
|
||||
= link_to namespace_project_issue_url(@new_project.namespace, @new_project, @new_issue) do
|
||||
= @new_issue.title
|
||||
@@ -0,0 +1,4 @@
|
||||
Issue was moved to another project.
|
||||
|
||||
New issue location:
|
||||
<%= namespace_project_issue_url(@new_project.namespace, @new_project, @new_issue) %>
|
||||
@@ -8,7 +8,7 @@
|
||||
= key.fingerprint
|
||||
.pull-right
|
||||
%span.key-created-at
|
||||
created #{time_ago_with_tooltip(key.created_at)} ago
|
||||
created #{time_ago_with_tooltip(key.created_at)}
|
||||
= link_to path_to_key(key, is_admin), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-transparent prepend-left-10" do
|
||||
%span.sr-only Remove
|
||||
= icon('trash')
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
- if branch.name == @repository.root_ref
|
||||
%span.label.label-primary default
|
||||
- elsif @repository.merged_to_root_ref? branch.name
|
||||
%span.label.label-info.has_tooltip(title="Merged into #{@repository.root_ref}")
|
||||
%span.label.label-info.has-tooltip(title="Merged into #{@repository.root_ref}")
|
||||
merged
|
||||
|
||||
- if @project.protected_branch? branch.name
|
||||
@@ -30,7 +30,7 @@
|
||||
Compare
|
||||
|
||||
- if can_remove_branch?(@project, branch.name)
|
||||
= link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has_tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do
|
||||
= link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-grouped btn-xs btn-remove remove-row has-tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do
|
||||
= icon("trash-o")
|
||||
|
||||
- if branch.name != @repository.root_ref
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- unless @project.empty_repo?
|
||||
- if can? current_user, :download_code, @project
|
||||
= link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn has_tooltip', data: {container: "body"}, rel: 'nofollow', title: "Download ZIP" do
|
||||
= link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn has-tooltip', data: {container: "body"}, rel: 'nofollow', title: "Download ZIP" do
|
||||
= icon('download')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- unless @project.empty_repo?
|
||||
- if current_user && can?(current_user, :fork_project, @project)
|
||||
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
|
||||
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has_tooltip' do
|
||||
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do
|
||||
= icon('code-fork fw')
|
||||
Fork
|
||||
%div.count-with-arrow
|
||||
@@ -9,7 +9,7 @@
|
||||
%span.count
|
||||
= @project.forks_count
|
||||
- else
|
||||
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has_tooltip' do
|
||||
= link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do
|
||||
= icon('code-fork fw')
|
||||
Fork
|
||||
%div.count-with-arrow
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
= notification_list_item(level, @membership)
|
||||
|
||||
- when GroupMember
|
||||
.btn.disabled.notifications-btn.has_tooltip{title: "To change the notification level, you need to be a member of the project itself, not only its group."}
|
||||
.btn.disabled.notifications-btn.has-tooltip{title: "To change the notification level, you need to be a member of the project itself, not only its group."}
|
||||
= icon('bell')
|
||||
= notification_label(@membership)
|
||||
= icon('angle-down')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
- if current_user
|
||||
= link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has_tooltip', method: :post, remote: true, title: "Star project" do
|
||||
= link_to toggle_star_namespace_project_path(@project.namespace, @project), class: 'btn star-btn toggle-star has-tooltip', method: :post, remote: true, title: "Star project" do
|
||||
- if current_user.starred?(@project)
|
||||
= icon('star fw')
|
||||
%span.starred Unstar
|
||||
@@ -12,7 +12,7 @@
|
||||
= @project.star_count
|
||||
|
||||
- else
|
||||
= link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do
|
||||
= link_to new_user_session_path, class: 'btn has-tooltip star-btn', title: 'You must sign in to star a project' do
|
||||
= icon('star fw')
|
||||
Star
|
||||
%div.count-with-arrow
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user