Commit 41f8e6a4 authored by Long Nguyen's avatar Long Nguyen

Merge branch 'master' of https://gitlab.com/gitlab-org/gitlab-ce into...

Merge branch 'master' of https://gitlab.com/gitlab-org/gitlab-ce into issue_17479_todos_not_remove_when_leave_project
parents 3a3c39b5 2485bd7b
...@@ -4,46 +4,46 @@ ...@@ -4,46 +4,46 @@
.bundle .bundle
.chef .chef
.directory .directory
.envrc /.envrc
.gitlab_shell_secret /.gitlab_shell_secret
.idea .idea
.rbenv-version /.rbenv-version
.rbx/ .rbx/
.ruby-gemset /.ruby-gemset
.ruby-version /.ruby-version
.rvmrc /.rvmrc
.sass-cache/ .sass-cache/
.secret /.secret
.vagrant /.vagrant
.byebug_history /.byebug_history
Vagrantfile /Vagrantfile
backups/* /backups/*
config/aws.yml /config/aws.yml
config/database.yml /config/database.yml
config/gitlab.yml /config/gitlab.yml
config/gitlab_ci.yml /config/gitlab_ci.yml
config/initializers/rack_attack.rb /config/initializers/rack_attack.rb
config/initializers/smtp_settings.rb /config/initializers/smtp_settings.rb
config/initializers/relative_url.rb /config/initializers/relative_url.rb
config/resque.yml /config/resque.yml
config/unicorn.rb /config/unicorn.rb
config/secrets.yml /config/secrets.yml
config/sidekiq.yml /config/sidekiq.yml
coverage/* /coverage/*
db/*.sqlite3 /db/*.sqlite3
db/*.sqlite3-journal /db/*.sqlite3-journal
db/data.yml /db/data.yml
doc/code/* /doc/code/*
dump.rdb /dump.rdb
log/*.log* /log/*.log*
nohup.out /nohup.out
public/assets/ /public/assets/
public/uploads.* /public/uploads.*
public/uploads/ /public/uploads/
shared/artifacts/ /shared/artifacts/
rails_best_practices_output.html /rails_best_practices_output.html
/tags /tags
tmp/ /tmp/*
vendor/bundle/* /vendor/bundle/*
builds/* /builds/*
shared/* /shared/*
This diff is collapsed.
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.8.0 (unreleased) v 8.9.0 (unreleased)
- Allow forking projects with restricted visibility level
- Improve note validation to prevent errors when creating invalid note via API
- Redesign navigation for project pages
- Fix groups API to list only user's accessible projects
- Redesign account and email confirmation emails
- Use gitlab-shell v3.0.0
- Add DB index on users.state
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- Fix issues filter when ordering by milestone
- Todos will display target state if issuable target is 'Closed' or 'Merged'
- Remove 'main language' feature
- Projects pending deletion will render a 404 page
- Measure queue duration between gitlab-workhorse and Rails
v 8.8.3
- Fix gitlab importer failing to import new projects due to missing credentials
- Fix import URL migration not rescuing with the correct Error
v 8.8.2
- Added remove due date button. !4209
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242
- Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245
- Fix table UI on CI builds page. !4249
- Fix backups if registry is disabled. !4263
- Fixed issue with merge button color. !4211
- Fixed issue with enter key selecting wrong option in dropdown. !4210
- When creating a .gitignore file a dropdown with templates will be provided. !4075
- Fix concurrent request when updating build log in browser. !4183
v 8.8.1
- Add documentation for the "Health Check" feature
- Allow anonymous users to access a public project's pipelines !4233
- Fix MySQL compatibility in zero downtime migrations helpers
- Fix the CI login to Container Registry (the gitlab-ci-token user)
v 8.8.0
- Implement GFM references for milestones (Alejandro Rodríguez) - Implement GFM references for milestones (Alejandro Rodríguez)
- Snippets tab under user profile. !4001 (Long Nguyen) - Snippets tab under user profile. !4001 (Long Nguyen)
- Fix error when using link to uploads in global snippets - Fix error when using link to uploads in global snippets
...@@ -13,6 +50,7 @@ v 8.8.0 (unreleased) ...@@ -13,6 +50,7 @@ v 8.8.0 (unreleased)
- Added inline diff styling for `change_title` system notes. (Adam Butler) - Added inline diff styling for `change_title` system notes. (Adam Butler)
- Project#open_branches has been cleaned up and no longer loads entire records into memory. - Project#open_branches has been cleaned up and no longer loads entire records into memory.
- Escape HTML in commit titles in system note messages - Escape HTML in commit titles in system note messages
- Improve design of Pipeline View
- Fix scope used when accessing container registry - Fix scope used when accessing container registry
- Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios - Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios
- Improve multiple branch push performance by memoizing permission checking - Improve multiple branch push performance by memoizing permission checking
...@@ -74,10 +112,14 @@ v 8.8.0 (unreleased) ...@@ -74,10 +112,14 @@ v 8.8.0 (unreleased)
- Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs) - Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs)
- When creating a .gitignore file a dropdown with templates will be provided - When creating a .gitignore file a dropdown with templates will be provided
v 8.7.7
- Fix import by `Any Git URL` broken if the URL contains a space
v 8.7.6 v 8.7.6
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko) - Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
- Fix import from GitLab.com to a private instance failure. !4181 - Fix import from GitLab.com to a private instance failure. !4181
- Fix external imports not finding the import data. !4106 - Fix external imports not finding the import data. !4106
- Fix notification delay when changing status of an issue
v 8.7.5 v 8.7.5
- Fix relative links in wiki pages. !4050 - Fix relative links in wiki pages. !4050
......
...@@ -121,7 +121,7 @@ group :unicorn do ...@@ -121,7 +121,7 @@ group :unicorn do
end end
# State machine # State machine
gem "state_machines-activerecord", '~> 0.3.0' gem "state_machines-activerecord", '~> 0.4.0'
# Run events after state machine commits # Run events after state machine commits
gem 'after_commit_queue' gem 'after_commit_queue'
...@@ -178,9 +178,6 @@ gem 'ruby-fogbugz', '~> 0.2.1' ...@@ -178,9 +178,6 @@ gem 'ruby-fogbugz', '~> 0.2.1'
# d3 # d3
gem 'd3_rails', '~> 3.5.0' gem 'd3_rails', '~> 3.5.0'
#cal-heatmap
gem 'cal-heatmap-rails', '~> 3.6.0'
# underscore-rails # underscore-rails
gem "underscore-rails", "~> 1.8.0" gem "underscore-rails", "~> 1.8.0"
...@@ -293,9 +290,10 @@ group :development, :test do ...@@ -293,9 +290,10 @@ group :development, :test do
gem 'spring-commands-spinach', '~> 1.1.0' gem 'spring-commands-spinach', '~> 1.1.0'
gem 'spring-commands-teaspoon', '~> 0.0.2' gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.38.0', require: false gem 'rubocop', '~> 0.40.0', require: false
gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.11.0', require: false gem 'simplecov', '~> 0.11.0', require: false
gem 'flog', require: false gem 'flog', require: false
gem 'flay', require: false gem 'flay', require: false
...@@ -325,7 +323,7 @@ gem "mail_room", "~> 0.7" ...@@ -325,7 +323,7 @@ gem "mail_room", "~> 0.7"
gem 'email_reply_parser', '~> 0.5.8' gem 'email_reply_parser', '~> 0.5.8'
## CI ## CI
gem 'activerecord-session_store', '~> 0.1.0' gem 'activerecord-session_store', '~> 1.0.0'
gem "nested_form", '~> 0.3.2' gem "nested_form", '~> 0.3.2'
# OAuth # OAuth
......
...@@ -33,10 +33,12 @@ GEM ...@@ -33,10 +33,12 @@ GEM
activemodel (= 4.2.6) activemodel (= 4.2.6)
activesupport (= 4.2.6) activesupport (= 4.2.6)
arel (~> 6.0) arel (~> 6.0)
activerecord-session_store (0.1.2) activerecord-session_store (1.0.0)
actionpack (>= 4.0.0, < 5) actionpack (>= 4.0, < 5.1)
activerecord (>= 4.0.0, < 5) activerecord (>= 4.0, < 5.1)
railties (>= 4.0.0, < 5) multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0, < 5.1)
activesupport (4.2.6) activesupport (4.2.6)
i18n (~> 0.7) i18n (~> 0.7)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
...@@ -100,7 +102,6 @@ GEM ...@@ -100,7 +102,6 @@ GEM
bundler (~> 1.2) bundler (~> 1.2)
thor (~> 0.18) thor (~> 0.18)
byebug (8.2.1) byebug (8.2.1)
cal-heatmap-rails (3.6.0)
capybara (2.6.2) capybara (2.6.2)
addressable addressable
mime-types (>= 1.16) mime-types (>= 1.16)
...@@ -549,7 +550,7 @@ GEM ...@@ -549,7 +550,7 @@ GEM
orm_adapter (0.5.0) orm_adapter (0.5.0)
paranoia (2.1.4) paranoia (2.1.4)
activerecord (~> 4.0) activerecord (~> 4.0)
parser (2.3.0.6) parser (2.3.1.0)
ast (~> 2.2) ast (~> 2.2)
pg (0.18.4) pg (0.18.4)
poltergeist (1.9.0) poltergeist (1.9.0)
...@@ -684,15 +685,17 @@ GEM ...@@ -684,15 +685,17 @@ GEM
rspec-retry (0.4.5) rspec-retry (0.4.5)
rspec-core rspec-core
rspec-support (3.4.1) rspec-support (3.4.1)
rubocop (0.38.0) rubocop (0.40.0)
parser (>= 2.3.0.6, < 3.0) parser (>= 2.3.1.0, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
rubocop-rspec (1.5.0)
rubocop (>= 0.40.0)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-progressbar (1.7.5) ruby-progressbar (1.8.1)
ruby-saml (1.1.2) ruby-saml (1.1.2)
nokogiri (>= 1.5.10) nokogiri (>= 1.5.10)
uuid (~> 2.3) uuid (~> 2.3)
...@@ -786,11 +789,11 @@ GEM ...@@ -786,11 +789,11 @@ GEM
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
state_machines (0.4.0) state_machines (0.4.0)
state_machines-activemodel (0.3.0) state_machines-activemodel (0.4.0)
activemodel (~> 4.1) activemodel (>= 4.1, < 5.1)
state_machines (>= 0.4.0) state_machines (>= 0.4.0)
state_machines-activerecord (0.3.0) state_machines-activerecord (0.4.0)
activerecord (~> 4.1) activerecord (>= 4.1, < 5.1)
state_machines-activemodel (>= 0.3.0) state_machines-activemodel (>= 0.3.0)
stringex (2.5.2) stringex (2.5.2)
systemu (2.6.5) systemu (2.6.5)
...@@ -839,7 +842,7 @@ GEM ...@@ -839,7 +842,7 @@ GEM
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.2) unf_ext (0.0.7.2)
unicode-display_width (1.0.2) unicode-display_width (1.0.5)
unicorn (4.9.0) unicorn (4.9.0)
kgio (~> 2.6) kgio (~> 2.6)
rack rack
...@@ -883,7 +886,7 @@ PLATFORMS ...@@ -883,7 +886,7 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
RedCloth (~> 4.2.9) RedCloth (~> 4.2.9)
ace-rails-ap (~> 4.0.2) ace-rails-ap (~> 4.0.2)
activerecord-session_store (~> 0.1.0) activerecord-session_store (~> 1.0.0)
acts-as-taggable-on (~> 3.4) acts-as-taggable-on (~> 3.4)
addressable (~> 2.3.8) addressable (~> 2.3.8)
after_commit_queue after_commit_queue
...@@ -904,7 +907,6 @@ DEPENDENCIES ...@@ -904,7 +907,6 @@ DEPENDENCIES
bullet bullet
bundler-audit bundler-audit
byebug byebug
cal-heatmap-rails (~> 3.6.0)
capybara (~> 2.6.2) capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0) capybara-screenshot (~> 1.0.0)
carrierwave (~> 0.10.0) carrierwave (~> 0.10.0)
...@@ -1013,7 +1015,8 @@ DEPENDENCIES ...@@ -1013,7 +1015,8 @@ DEPENDENCIES
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.4.0) rspec-rails (~> 3.4.0)
rspec-retry rspec-retry
rubocop (~> 0.38.0) rubocop (~> 0.40.0)
rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 5.0.0) sass-rails (~> 5.0.0)
...@@ -1038,7 +1041,7 @@ DEPENDENCIES ...@@ -1038,7 +1041,7 @@ DEPENDENCIES
spring-commands-spinach (~> 1.1.0) spring-commands-spinach (~> 1.1.0)
spring-commands-teaspoon (~> 0.0.2) spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 3.6.0) sprockets (~> 3.6.0)
state_machines-activerecord (~> 0.3.0) state_machines-activerecord (~> 0.4.0)
task_list (~> 1.0.2) task_list (~> 1.0.2)
teaspoon (~> 1.1.0) teaspoon (~> 1.1.0)
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
...@@ -1058,4 +1061,4 @@ DEPENDENCIES ...@@ -1058,4 +1061,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.12.3 1.12.4
8.8.0-pre 8.9.0-pre
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#= require jquery.scrollTo #= require jquery.scrollTo
#= require jquery.turbolinks #= require jquery.turbolinks
#= require d3 #= require d3
#= require cal-heatmap
#= require turbolinks #= require turbolinks
#= require autosave #= require autosave
#= require bootstrap/affix #= require bootstrap/affix
...@@ -246,38 +245,6 @@ $ -> ...@@ -246,38 +245,6 @@ $ ->
if $navIcon.hasClass('fa-angle-left') if $navIcon.hasClass('fa-angle-left')
$navIconToggle.trigger('click') $navIconToggle.trigger('click')
$(document)
.off 'click', '.js-sidebar-toggle'
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
e.preventDefault()
$this = $(this)
$thisIcon = $this.find 'i'
$allGutterToggleIcons = $('.js-sidebar-toggle i')
if $thisIcon.hasClass('fa-angle-double-right')
$allGutterToggleIcons
.removeClass('fa-angle-double-right')
.addClass('fa-angle-double-left')
$('aside.right-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
$('.page-with-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
else
$allGutterToggleIcons
.removeClass('fa-angle-double-left')
.addClass('fa-angle-double-right')
$('aside.right-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
$('.page-with-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
if not triggered
$.cookie("collapsed_gutter",
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
fitSidebarForSize = -> fitSidebarForSize = ->
oldBootstrapBreakpoint = bootstrapBreakpoint oldBootstrapBreakpoint = bootstrapBreakpoint
bootstrapBreakpoint = bp.getBreakpointSize() bootstrapBreakpoint = bp.getBreakpointSize()
......
class @Calendar class @Calendar
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) -> constructor: (timestamps, @calendar_activities_path) ->
cal = new CalHeatMap() @currentSelectedDate = ''
cal.init @daySpace = 1
itemName: ["contribution"] @daySize = 15
data: timestamps @daySizeWithSpace = @daySize + (@daySpace * 2)
start: new Date(starting_year, starting_month) @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
domainLabelFormat: "%b" @months = []
id: "cal-heatmap" @highestValue = 0
domain: "month"
subDomain: "day"
range: 12
tooltip: true
label:
position: "top"
legend: [
0
10
20
30
]
legendCellPadding: 3
cellSize: $('.user-calendar').width() / 73
onClick: (date, count) ->
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax
url: calendar_activities_path
data:
date: formated_date
cache: false
dataType: "html"
success: (data) ->
$(".user-calendar-activities").html data
# Get the highest value from the timestampes
_.each timestamps, (count) =>
if count > @highestValue
@highestValue = count
# Loop through the timestamps to create a group of objects
# The group of objects will be grouped based on the day of the week they are
@timestampsTmp = []
i = 0
group = 0
_.each timestamps, (count, date) =>
newDate = new Date parseInt(date) * 1000
day = newDate.getDay()
# Create a new group array if this is the first day of the week
# or if is first object
if (day is 0 and i isnt 0) or i is 0
@timestampsTmp.push []
group++
innerArray = @timestampsTmp[group-1]
# Push to the inner array the values that will be used to render map
innerArray.push
count: count
date: newDate
day: day
i++
# Init color functions
@color = @initColor()
@colorKey = @initColorKey()
# Init the svg element
@renderSvg(group)
@renderDays()
@renderMonths()
@renderDayTitles()
@renderKey()
@initTooltips()
renderSvg: (group) ->
@svg = d3.select '.js-contrib-calendar'
.append 'svg'
.attr 'width', (group + 1) * @daySizeWithSpace
.attr 'height', 167
.attr 'class', 'contrib-calendar'
renderDays: ->
@svg.selectAll 'g'
.data @timestampsTmp
.enter()
.append 'g'
.attr 'transform', (group, i) =>
_.each group, (stamp, a) =>
if a is 0 and stamp.day is 0
month = stamp.date.getMonth()
x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
lastMonth = _.last(@months)
if lastMonth?
lastMonthX = lastMonth.x
if !lastMonth?
@months.push
month: month
x: x
else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
@months.push
month: month
x: x
"translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
.selectAll 'rect'
.data (stamp) ->
stamp
.enter()
.append 'rect'
.attr 'x', '0'
.attr 'y', (stamp, i) =>
(@daySizeWithSpace * stamp.day)
.attr 'width', @daySize
.attr 'height', @daySize
.attr 'title', (stamp) =>
contribText = 'No contributions'
if stamp.count > 0
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
date = dateFormat(stamp.date, 'mmm d, yyyy')
"#{contribText}<br />#{date}"
.attr 'class', 'user-contrib-cell js-tooltip'
.attr 'fill', (stamp) =>
if stamp.count isnt 0
@color(stamp.count)
else
'#ededed'
.attr 'data-container', 'body'
.on 'click', @clickDay
renderDayTitles: ->
days = [{
text: 'M'
y: 29 + (@daySizeWithSpace * 1)
}, {
text: 'W'
y: 29 + (@daySizeWithSpace * 3)
}, {
text: 'F'
y: 29 + (@daySizeWithSpace * 5)
}]
@svg.append 'g'
.selectAll 'text'
.data days
.enter()
.append 'text'
.attr 'text-anchor', 'middle'
.attr 'x', 8
.attr 'y', (day) ->
day.y
.text (day) ->
day.text
.attr 'class', 'user-contrib-text'
renderMonths: ->
@svg.append 'g'
.selectAll 'text'
.data @months
.enter()
.append 'text'
.attr 'x', (date) ->
date.x
.attr 'y', 10
.attr 'class', 'user-contrib-text'
.text (date) =>
@monthNames[date.month]
renderKey: ->
keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
@svg.append 'g'
.attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
.selectAll 'rect'
.data keyColors
.enter()
.append 'rect'
.attr 'width', @daySize
.attr 'height', @daySize
.attr 'x', (color, i) =>
@daySizeWithSpace * i
.attr 'y', 0
.attr 'fill', (color) ->
color
initColor: ->
d3.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, @highestValue])
initColorKey: ->
d3.scale
.linear()
.range(['#acd5f2', '#254e77'])
.domain([0, 3])
clickDay: (stamp) =>
if @currentSelectedDate isnt stamp.date
@currentSelectedDate = stamp.date
formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()
$.ajax
url: @calendar_activities_path
data:
date: formatted_date
cache: false
dataType: 'html'
beforeSend: ->
$('.user-calendar-activities').html '<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>'
success: (data) ->
$('.user-calendar-activities').html data
else
$('.user-calendar-activities').html ''
initTooltips: ->
$('.js-contrib-calendar .js-tooltip').tooltip
html: true
...@@ -28,12 +28,15 @@ class CiBuild ...@@ -28,12 +28,15 @@ class CiBuild
# #
CiBuild.interval = setInterval => CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url if window.location.href.split("#").first() is build_url
last_state = @state
$.ajax $.ajax
url: build_url + "/trace.json?state=" + encodeURIComponent(@state) url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
dataType: "json" dataType: "json"
success: (log) => success: (log) =>
@state = log.state return unless last_state is @state
if log.status is "running"
if log.state and log.status is "running"
@state = log.state
if log.append if log.append
$('.fa-refresh').before log.html $('.fa-refresh').before log.html
else else
......
...@@ -16,7 +16,6 @@ class Dispatcher ...@@ -16,7 +16,6 @@ class Dispatcher
shortcut_handler = null shortcut_handler = null
switch page switch page
when 'projects:issues:index' when 'projects:issues:index'
Issues.init()
Issuable.init() Issuable.init()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:issues:show' when 'projects:issues:show'
...@@ -119,7 +118,7 @@ class Dispatcher ...@@ -119,7 +118,7 @@ class Dispatcher
new UsersSelect() new UsersSelect()
when 'projects' when 'projects'
new NamespaceSelect() new NamespaceSelect()
when 'dashboard' when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation() shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles' when 'profiles'
new Profile() new Profile()
......
...@@ -11,6 +11,7 @@ class @DueDateSelect ...@@ -11,6 +11,7 @@ class @DueDateSelect
$block = $dropdown.closest('.block') $block = $dropdown.closest('.block')
$selectbox = $dropdown.closest('.selectbox') $selectbox = $dropdown.closest('.selectbox')
$value = $block.find('.value') $value = $block.find('.value')
$valueContent = $block.find('.value-content')
$sidebarValue = $('.js-due-date-sidebar-value', $block) $sidebarValue = $('.js-due-date-sidebar-value', $block)
fieldName = $dropdown.data('field-name') fieldName = $dropdown.data('field-name')
...@@ -23,11 +24,15 @@ class @DueDateSelect ...@@ -23,11 +24,15 @@ class @DueDateSelect
$value.removeAttr('style') $value.removeAttr('style')
) )
addDueDate = -> addDueDate = (isDropdown) ->
# Create the post date # Create the post date
value = $("input[name='#{fieldName}']").val() value = $("input[name='#{fieldName}']").val()
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date if value isnt ''
date = new Date value.replace(new RegExp('-', 'g'), ',')
mediumDate = $.datepicker.formatDate 'M d, yy', date
else
mediumDate = 'None'
data = {} data = {}
data[abilityName] = {} data[abilityName] = {}
...@@ -39,23 +44,35 @@ class @DueDateSelect ...@@ -39,23 +44,35 @@ class @DueDateSelect
data: data data: data
beforeSend: -> beforeSend: ->
$loading.fadeIn() $loading.fadeIn()
$dropdown.trigger('loading.gl.dropdown') if isDropdown
$selectbox.hide() $dropdown.trigger('loading.gl.dropdown')
$selectbox.hide()
$value.removeAttr('style') $value.removeAttr('style')
$value.html(mediumDate) $valueContent.html(mediumDate)
$sidebarValue.html(mediumDate) $sidebarValue.html(mediumDate)
if value isnt ''
$('.js-remove-due-date-holder').removeClass 'hidden'
else
$('.js-remove-due-date-holder').addClass 'hidden'
).done (data) -> ).done (data) ->
$dropdown.trigger('loaded.gl.dropdown') if isDropdown
$dropdown.dropdown('toggle') $dropdown.trigger('loaded.gl.dropdown')
$dropdown.dropdown('toggle')
$loading.fadeOut() $loading.fadeOut()
$block.on 'click', '.js-remove-due-date', (e) ->
e.preventDefault()
$("input[name='#{fieldName}']").val ''
addDueDate(false)
$datePicker.datepicker( $datePicker.datepicker(
dateFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd',
defaultDate: $("input[name='#{fieldName}']").val() defaultDate: $("input[name='#{fieldName}']").val()
altField: "input[name='#{fieldName}']" altField: "input[name='#{fieldName}']"
onSelect: -> onSelect: ->
addDueDate() addDueDate(true)
) )
$(document) $(document)
......
issuable_created = false
@Issuable = @Issuable =
init: -> init: ->
Issuable.initTemplates() unless issuable_created
Issuable.initSearch() issuable_created = true
Issuable.initTemplates()
Issuable.initSearch()
Issuable.initChecks()
initTemplates: -> initTemplates: ->
Issuable.labelRow = _.template( Issuable.labelRow = _.template(
...@@ -19,7 +23,16 @@ ...@@ -19,7 +23,16 @@
.on 'keyup', -> .on 'keyup', ->
clearTimeout(@timer) clearTimeout(@timer)
@timer = setTimeout( -> @timer = setTimeout( ->
Issuable.filterResults $('#issue_search_form') $search = $('#issue_search')
$form = $('.js-filter-form')
$input = $("input[name='#{$search.attr('name')}']", $form)
if $input.length is 0
$form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>"
else
$input.val $search.val()
Issuable.filterResults $form
, 500) , 500)
toggleLabelFilters: -> toggleLabelFilters: ->
...@@ -59,15 +72,22 @@ ...@@ -59,15 +72,22 @@
dataType: "json" dataType: "json"
reload: -> reload: ->
if Issues.created if Issuable.created
Issues.initChecks() Issuable.initChecks()
$('#filter_issue_search').val($('#issue_search').val()) $('#filter_issue_search').val($('#issue_search').val())
initChecks: ->
$('.check_all_issues').on 'click', ->
$('.selected_issue').prop('checked', @checked)
Issuable.checkChanged()
$('.selected_issue').on 'change', Issuable.checkChanged
updateStateFilters: -> updateStateFilters: ->
stateFilters = $('.issues-state-filters') stateFilters = $('.issues-state-filters, .dropdown-menu-sort')
newParams = {} newParams = {}
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search'] paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search', 'issue_search']
for paramKey in paramKeys for paramKey in paramKeys
newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or '' newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
...@@ -82,3 +102,17 @@ ...@@ -82,3 +102,17 @@
else else
newUrl = gl.utils.mergeUrlParams(newParams, initialUrl) newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
$(this).attr 'href', newUrl $(this).attr 'href', newUrl
checkChanged: ->
checked_issues = $('.selected_issue:checked')
if checked_issues.length > 0
ids = $.map checked_issues, (value) ->
$(value).data('id')
$('#update_issues_ids').val ids
$('.issues-other-filters').hide()
$('.issues_bulk_update').show()
else
$('#update_issues_ids').val []
$('.issues_bulk_update').hide()
$('.issues-other-filters').show()
...@@ -19,6 +19,7 @@ class @IssuableForm ...@@ -19,6 +19,7 @@ class @IssuableForm
@form.on "click", ".btn-cancel", @resetAutosave @form.on "click", ".btn-cancel", @resetAutosave
@initWip() @initWip()
@initMoveDropdown()
$issuableDueDate = $('#issuable-due-date') $issuableDueDate = $('#issuable-due-date')
...@@ -89,3 +90,19 @@ class @IssuableForm ...@@ -89,3 +90,19 @@ class @IssuableForm
addWip: -> addWip: ->
@titleField.val "WIP: #{@titleField.val()}" @titleField.val "WIP: #{@titleField.val()}"
initMoveDropdown: ->
$moveDropdown = $('.js-move-dropdown')
if $moveDropdown.length
$('.js-move-dropdown').select2
ajax:
url: $moveDropdown.data('projects-url')
results: (data) ->
return {
results: data
}
formatResult: (project) ->
project.name_with_namespace
formatSelection: (project) ->
project.name_with_namespace
@Issues =
init: ->
Issues.created = true
Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
t = $(this)
totalIssues = undefined
reopen = t.hasClass("reopen_issue")
$(".issue_counter").each ->
issue = $(this)
totalIssues = parseInt($(this).html(), 10)
if reopen and issue.closest(".main_menu").length
$(this).html totalIssues + 1
else
$(this).html totalIssues - 1
initChecks: ->
$(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked)
Issues.checkChanged()
$(".selected_issue").bind "change", Issues.checkChanged
checkChanged: ->
checked_issues = $(".selected_issue:checked")
if checked_issues.length > 0
ids = []
$.each checked_issues, (index, value) ->
ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids
$(".issues-other-filters").hide()
$(".issues_bulk_update").show()
else
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-other-filters").show()
class @LayoutNav
$ ->
$('.fade-left').addClass('end-scroll')
$('.scrolling-tabs').on 'scroll', (event) ->
$this = $(this)
$el = $(event.target)
currentPosition = $this.scrollLeft()
size = bp.getBreakpointSize()
controlBtnWidth = $('.controls').width()
maxPosition = $this.get(0).scrollWidth - $this.parent().width()
maxPosition += controlBtnWidth if size isnt 'xs' and $('.nav-control').length
$el.find('.fade-left').toggleClass('end-scroll', currentPosition is 0)
$el.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition)
...@@ -26,10 +26,19 @@ ...@@ -26,10 +26,19 @@
newUrl = decodeURIComponent(url) newUrl = decodeURIComponent(url)
for paramName, paramValue of params for paramName, paramValue of params
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)" pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
if url.search(pattern) >= 0 if not paramValue?
newUrl = newUrl.replace pattern, ''
else if url.search(pattern) isnt -1
newUrl = newUrl.replace pattern, "$1#{paramValue}$2" newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
else else
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}" newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
# Remove a trailing ampersand
lastChar = newUrl[newUrl.length - 1]
if lastChar is '&'
newUrl = newUrl.slice 0, -1
newUrl newUrl
# removes parameter query string from url. returns the modified url # removes parameter query string from url. returns the modified url
......
...@@ -75,6 +75,9 @@ class @MergeRequestTabs ...@@ -75,6 +75,9 @@ class @MergeRequestTabs
@loadDiff($target.attr('href')) @loadDiff($target.attr('href'))
if bp? and bp.getBreakpointSize() isnt 'lg' if bp? and bp.getBreakpointSize() isnt 'lg'
@shrinkView() @shrinkView()
navBarHeight = $('.navbar-gitlab').outerHeight()
$.scrollTo(".merge-request-details .merge-request-tabs", offset: -navBarHeight)
else if action == 'builds' else if action == 'builds'
@loadBuilds($target.attr('href')) @loadBuilds($target.attr('href'))
@expandView() @expandView()
......
...@@ -10,6 +10,7 @@ class @MergeRequestWidget ...@@ -10,6 +10,7 @@ class @MergeRequestWidget
$('#modal_merge_info').modal(show: false) $('#modal_merge_info').modal(show: false)
@firstCICheck = true @firstCICheck = true
@readyForCICheck = false @readyForCICheck = false
@cancel = false
clearInterval @fetchBuildStatusInterval clearInterval @fetchBuildStatusInterval
@clearEventListeners() @clearEventListeners()
...@@ -21,10 +22,16 @@ class @MergeRequestWidget ...@@ -21,10 +22,16 @@ class @MergeRequestWidget
clearEventListeners: -> clearEventListeners: ->
$(document).off 'page:change.merge_request' $(document).off 'page:change.merge_request'
cancelPolling: ->
@cancel = true
addEventListeners: -> addEventListeners: ->
allowedPages = ['show', 'commits', 'builds', 'changes']
$(document).on 'page:change.merge_request', => $(document).on 'page:change.merge_request', =>
if $('body').data('page') isnt 'projects:merge_requests:show' page = $('body').data('page').split(':').last()
if allowedPages.indexOf(page) < 0
clearInterval @fetchBuildStatusInterval clearInterval @fetchBuildStatusInterval
@cancelPolling()
@clearEventListeners() @clearEventListeners()
mergeInProgress: (deleteSourceBranch = false)-> mergeInProgress: (deleteSourceBranch = false)->
...@@ -67,6 +74,7 @@ class @MergeRequestWidget ...@@ -67,6 +74,7 @@ class @MergeRequestWidget
$('.ci-widget-fetching').show() $('.ci-widget-fetching').show()
$.getJSON @opts.ci_status_url, (data) => $.getJSON @opts.ci_status_url, (data) =>
return if @cancel
@readyForCICheck = true @readyForCICheck = true
if data.status is '' if data.status is ''
...@@ -106,6 +114,7 @@ class @MergeRequestWidget ...@@ -106,6 +114,7 @@ class @MergeRequestWidget
@firstCICheck = false @firstCICheck = false
showCIStatus: (state) -> showCIStatus: (state) ->
return if not state?
$('.ci_widget').hide() $('.ci_widget').hide()
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"] allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
if state in allowed_states if state in allowed_states
...@@ -126,6 +135,6 @@ class @MergeRequestWidget ...@@ -126,6 +135,6 @@ class @MergeRequestWidget
$('.ci_widget:visible .ci-coverage').text(text) $('.ci_widget:visible .ci-coverage').text(text)
setMergeButtonClass: (css_class) -> setMergeButtonClass: (css_class) ->
$('.js-merge-button') $('.js-merge-button,.accept-action .dropdown-toggle')
.removeClass('btn-danger btn-warning btn-create') .removeClass('btn-danger btn-warning btn-create')
.addClass(css_class) .addClass(css_class)
...@@ -114,9 +114,9 @@ class @Notes ...@@ -114,9 +114,9 @@ class @Notes
@refresh() @refresh()
, @pollingInterval , @pollingInterval
refresh: -> refresh: =>
return if @refreshing is true return if @refreshing is true
refreshing = true @refreshing = true
if not document.hidden and document.URL.indexOf(@noteable_url) is 0 if not document.hidden and document.URL.indexOf(@noteable_url) is 0
@getContent() @getContent()
...@@ -134,8 +134,8 @@ class @Notes ...@@ -134,8 +134,8 @@ class @Notes
@renderDiscussionNote(note) @renderDiscussionNote(note)
else else
@renderNote(note) @renderNote(note)
always: => .always () =>
@refreshing = false @refreshing = false
### ###
Increase @pollingInterval up to 120 seconds on every function call, Increase @pollingInterval up to 120 seconds on every function call,
...@@ -329,7 +329,7 @@ class @Notes ...@@ -329,7 +329,7 @@ class @Notes
@renderDiscussionNote(note) @renderDiscussionNote(note)
# cleanup after successfully creating a diff/discussion note # cleanup after successfully creating a diff/discussion note
@removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}")) @removeDiscussionNoteForm($(xhr.target))
### ###
Called in response to the edit note form being submitted Called in response to the edit note form being submitted
......
...@@ -10,6 +10,40 @@ class @Sidebar ...@@ -10,6 +10,40 @@ class @Sidebar
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading) $('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded) $('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
$(document)
.off 'click', '.js-sidebar-toggle'
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
e.preventDefault()
$this = $(this)
$thisIcon = $this.find 'i'
$allGutterToggleIcons = $('.js-sidebar-toggle i')
if $thisIcon.hasClass('fa-angle-double-right')
$allGutterToggleIcons
.removeClass('fa-angle-double-right')
.addClass('fa-angle-double-left')
$('aside.right-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
$('.page-with-sidebar')
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed')
else
$allGutterToggleIcons
.removeClass('fa-angle-double-left')
.addClass('fa-angle-double-right')
$('aside.right-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
$('.page-with-sidebar')
.removeClass('right-sidebar-collapsed')
.addClass('right-sidebar-expanded')
if not triggered
$.cookie("collapsed_gutter",
$('.right-sidebar')
.hasClass('right-sidebar-collapsed'), { path: '/' })
sidebarDropdownLoading: (e) -> sidebarDropdownLoading: (e) ->
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon') $sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
img = $sidebarCollapsedIcon.find('img') img = $sidebarCollapsedIcon.find('img')
...@@ -76,7 +110,7 @@ class @Sidebar ...@@ -76,7 +110,7 @@ class @Sidebar
@triggerOpenSidebar() if not @isOpen() @triggerOpenSidebar() if not @isOpen()
if action is 'hide' if action is 'hide'
@triggerOpenSidebar() is @isOpen() @triggerOpenSidebar() if @isOpen()
isOpen: -> isOpen: ->
@sidebar.is('.right-sidebar-expanded') @sidebar.is('.right-sidebar-expanded')
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
class @ShortcutsDashboardNavigation extends Shortcuts class @ShortcutsDashboardNavigation extends Shortcuts
constructor: -> constructor: ->
super() super()
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity')) Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues')) Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests')) Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects')) Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects'))
@findAndFollowLink: (selector) -> @findAndFollowLink: (selector) ->
link = $(selector).attr('href') link = $(selector).attr('href')
......
...@@ -93,7 +93,9 @@ class @UsersSelect ...@@ -93,7 +93,9 @@ class @UsersSelect
$dropdown.glDropdown( $dropdown.glDropdown(
data: (term, callback) => data: (term, callback) =>
@users term, (users) => isAuthorFilter = $('.js-author-search')
@users term, term is '' and isAuthorFilter, (users) =>
if term.length is 0 if term.length is 0
showDivider = 0 showDivider = 0
...@@ -138,7 +140,7 @@ class @UsersSelect ...@@ -138,7 +140,7 @@ class @UsersSelect
toggleLabel: (selected) -> toggleLabel: (selected) ->
if selected && 'id' of selected if selected && 'id' of selected
selected.name if selected.text then selected.text else selected.name
else else
defaultLabel defaultLabel
...@@ -219,7 +221,7 @@ class @UsersSelect ...@@ -219,7 +221,7 @@ class @UsersSelect
multiple: $(select).hasClass('multiselect') multiple: $(select).hasClass('multiselect')
minimumInputLength: 0 minimumInputLength: 0
query: (query) => query: (query) =>
@users query.term, (users) => @users query.term, @projectId?, (users) =>
data = { results: users } data = { results: users }
if query.term.length == 0 if query.term.length == 0
...@@ -302,7 +304,7 @@ class @UsersSelect ...@@ -302,7 +304,7 @@ class @UsersSelect
# Return users list. Filtered by query # Return users list. Filtered by query
# Only active users retrieved # Only active users retrieved
users: (query, callback) => users: (query, fromProject, callback) =>
url = @buildUrl(@usersPath) url = @buildUrl(@usersPath)
$.ajax( $.ajax(
...@@ -311,7 +313,7 @@ class @UsersSelect ...@@ -311,7 +313,7 @@ class @UsersSelect
search: query search: query
per_page: 20 per_page: 20
active: true active: true
project_id: @projectId project_id: @projectId if fromProject
group_id: @groupId group_id: @groupId
current_user: @showCurrentUser current_user: @showCurrentUser
author_id: @authorId author_id: @authorId
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
*= require select2 *= require select2
*= require_self *= require_self
*= require dropzone/basic *= require dropzone/basic
*= require cal-heatmap
*= require cropper.css *= require cropper.css
*/ */
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
&.s32 { font-size: 20px; line-height: 32px; } &.s32 { font-size: 20px; line-height: 32px; }
&.s40 { font-size: 16px; line-height: 40px; } &.s40 { font-size: 16px; line-height: 40px; }
&.s60 { font-size: 32px; line-height: 60px; } &.s60 { font-size: 32px; line-height: 60px; }
&.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 90px; } &.s90 { font-size: 36px; line-height: 90px; }
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
&.s140 { font-size: 72px; line-height: 140px; } &.s140 { font-size: 72px; line-height: 140px; }
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
background-color: $background-color; background-color: $background-color;
padding: $gl-padding; padding: $gl-padding;
margin-bottom: 0; margin-bottom: 0;
border-top: 1px solid $border-color; border-top: 1px solid $white-dark;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $white-dark;
color: $gl-gray; color: $gl-gray;
&.oneline-block { &.oneline-block {
...@@ -110,9 +110,9 @@ ...@@ -110,9 +110,9 @@
.cover-title { .cover-title {
color: $gl-header-color; color: $gl-header-color;
margin: 0; margin: 0;
font-size: 23px; font-size: 24px;
font-weight: normal; font-weight: normal;
margin: 16px 0 5px; margin-bottom: 5px;
color: #4c4e54; color: #4c4e54;
font-size: 23px; font-size: 23px;
line-height: 1.1; line-height: 1.1;
...@@ -137,7 +137,6 @@ ...@@ -137,7 +137,6 @@
} }
.cover-desc { .cover-desc {
padding: 0 $gl-padding 3px;
color: $gl-text-color; color: $gl-text-color;
&.username:last-child { &.username:last-child {
...@@ -205,7 +204,7 @@ ...@@ -205,7 +204,7 @@
.content-block { .content-block {
padding: $gl-padding 0; padding: $gl-padding 0;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $white-dark;
&.oneline-block { &.oneline-block {
line-height: 36px; line-height: 36px;
......
.calender-block { .calender-block {
padding-left: 0;
padding-right: 0;
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) { @media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
overflow-x: scroll; overflow-x: scroll;
} }
} }
.user-calendar-activities { .user-calendar-activities {
.calendar_onclick_hr {
padding: 0;
margin: 10px 0;
}
.str-truncated { .str-truncated {
max-width: 70%; max-width: 70%;
} }
.text-expander { .user-calendar-activities-loading {
background: #eee; font-size: 24px;
color: #555;
padding: 0 5px;
cursor: pointer;
margin-left: 4px;
&:hover {
background-color: #ddd;
}
} }
} }
/** .user-calendar {
* This overwrites the default values of the cal-heatmap gem text-align: center;
*/
.calendar {
.qi {
fill: #fff;
}
.q1 {
fill: #ededed !important;
}
.q2 { .calendar {
fill: #acd5f2 !important; display: inline-block;
}
.q3 {
fill: #7fa8d1 !important;
}
.q4 {
fill: #49729b !important;
}
.q5 {
fill: #254e77 !important;
} }
}
.future { .user-contrib-cell {
visibility: hidden; &:hover {
cursor: pointer;
stroke: #000;
} }
}
.domain-background { .user-contrib-text {
fill: none; font-size: 12px;
shape-rendering: crispedges; fill: #959494;
} }
.ch-tooltip { .calendar-hint {
padding: 3px; margin-top: -23px;
font-weight: 550; float: right;
} font-size: 12px;
} }
...@@ -154,7 +154,7 @@ ...@@ -154,7 +154,7 @@
color: $dropdown-header-color; color: $dropdown-header-color;
font-size: 13px; font-size: 13px;
line-height: 22px; line-height: 22px;
padding: 0 10px 10px; padding: 0 10px;
} }
.separator + .dropdown-header { .separator + .dropdown-header {
...@@ -162,6 +162,10 @@ ...@@ -162,6 +162,10 @@
} }
} }
.dropdown-menu-full-width {
width: 100%;
}
.dropdown-menu-paging { .dropdown-menu-paging {
.dropdown-page-two, .dropdown-page-two,
.dropdown-menu-back { .dropdown-menu-back {
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
.file-holder { .file-holder {
border: 1px solid $border-color; border: 1px solid $border-color;
&.file-holder-no-border {
border: 0;
}
&.readme-holder { &.readme-holder {
margin: $gl-padding-top 0; margin: $gl-padding-top 0;
} }
...@@ -23,8 +27,17 @@ ...@@ -23,8 +27,17 @@
word-wrap: break-word; word-wrap: break-word;
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
&.file-title-clear {
padding-left: 0;
padding-right: 0;
background-color: transparent;
.file-actions {
right: 0;
}
}
.file-actions { .file-actions {
float: right;
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 15px; right: 15px;
......
...@@ -48,10 +48,6 @@ ...@@ -48,10 +48,6 @@
display: block; display: block;
} }
.project-home-desc {
font-size: 21px;
}
.project-repo-buttons, .project-repo-buttons,
.git-clone-holder { .git-clone-holder {
display: none; display: none;
......
@mixin fade($gradient-direction, $rgba, $gradient-color) {
visibility: visible;
opacity: 1;
position: absolute;
bottom: 12px;
width: 43px;
height: 30px;
transition-duration: .3s;
-webkit-transform: translateZ(0);
background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
&.end-scroll {
visibility: hidden;
opacity: 0;
transition-duration: .3s;
}
}
@mixin scrolling-links() {
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
}
.nav-links { .nav-links {
padding: 0; padding: 0;
margin: 0; margin: 0;
...@@ -119,7 +150,7 @@ ...@@ -119,7 +150,7 @@
} }
input { input {
height: 34px; height: 35px;
display: inline-block; display: inline-block;
position: relative; position: relative;
top: 2px; top: 2px;
...@@ -196,7 +227,7 @@ ...@@ -196,7 +227,7 @@
position: fixed; position: fixed;
top: $header-height; top: $header-height;
width: 100%; width: 100%;
z-index: 1; z-index: 11;
background: $background-color; background: $background-color;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
transition-duration: .3s; transition-duration: .3s;
...@@ -209,13 +240,8 @@ ...@@ -209,13 +240,8 @@
float: right; float: right;
padding: 7px 0 0; padding: 7px 0 0;
@media (max-width: $screen-xs-min) { @media (max-width: $screen-xs-max) {
float: none; display: none;
padding: 0 9px;
.dropdown-new {
width: 100%;
}
} }
i { i {
...@@ -238,14 +264,27 @@ ...@@ -238,14 +264,27 @@
@media (max-width: $screen-xs-min) { @media (max-width: $screen-xs-min) {
margin-left: 0; margin-left: 0;
} }
li.active {
font-weight: bold;
}
} }
} }
.nav-links { .nav-links {
@include scrolling-links();
border-bottom: none; border-bottom: none;
height: 51px; height: 51px;
white-space: nowrap;
overflow-x: auto; .fade-right {
@include fade(left, rgba(250, 250, 250, 0.4), $background-color);
right: 0;
}
.fade-left {
@include fade(right, rgba(250, 250, 250, 0.4), $background-color);
left: 0;
}
li { li {
...@@ -269,14 +308,62 @@ ...@@ -269,14 +308,62 @@
} }
} }
.nav-control {
.fade-right {
@media (min-width: $screen-xs-max) {
right: 67px;
}
@media (max-width: $screen-xs-min) {
right: 0;
}
}
}
}
.nav-block {
position: relative;
.nav-links {
@include scrolling-links();
.fade-right {
@include fade(left, rgba(255, 255, 255, 0.4), $white-light);
right: 0;
}
.fade-left {
@include fade(right, rgba(255, 255, 255, 0.4), $white-light);
left: 0;
}
&.event-filter {
.fade-right {
visibility: hidden;
@media (max-width: $screen-xs-max) {
visibility: visible;
}
}
}
}
} }
.page-with-layout-nav { .page-with-layout-nav {
margin-top: 50px; margin-top: $header-height + 2;
.right-sidebar {
top: ($header-height * 2) + 2;
}
}
.activities {
.nav-block {
border-bottom: 1px solid $border-color;
&.controls-dropdown-visible { .nav-links {
@media (max-width: $screen-xs-min) { border-bottom: none;
margin-top: 96px;
} }
} }
} }
...@@ -324,7 +324,7 @@ ...@@ -324,7 +324,7 @@
.layout-nav { .layout-nav {
@media (max-width: $screen-xs-min) { @media (max-width: $screen-xs-min) {
padding-right: 0;; padding-right: 0;
} }
@media (min-width: $screen-xs-min) and (max-width: $screen-md-min) { @media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
......
...@@ -119,8 +119,8 @@ $border-white-light: #f1f2f4; ...@@ -119,8 +119,8 @@ $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2; $border-white-normal: #d6dae2;
$border-white-dark: #c6cacf; $border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06); $border-gray-light: #dcdcdc;
$border-gray-normal: rgba(0, 0, 0, 0.10);; $border-gray-normal: rgba(0, 0, 0, 0.10);
$border-gray-dark: #c6cacf; $border-gray-dark: #c6cacf;
$border-green-light: #2faa60; $border-green-light: #2faa60;
......
// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout
// used for Devise email templates, and _should not_ be included in any
// application stylesheets.
//
// Styles defined here are embedded directly into the resulting email HTML via
// the `premailer` gem.
$body-background-color: #363636;
$message-background-color: #fafafa;
$header-color: #6b4fbb;
$body-color: #444;
$cta-color: #e14329;
$footer-link-color: #7e7e7e;
$font-family: Helvetica, Arial, sans-serif;
body {
background-color: $body-background-color;
font-family: $font-family;
margin: 0;
padding: 0;
}
table {
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
border: 0;
border-collapse: separate;
&#wrapper {
background-color: $body-background-color;
width: 100%;
}
&#header {
margin: 0 auto;
text-align: left;
width: 600px;
}
&#body {
background-color: $message-background-color;
border: 1px solid #000;
border-radius: 4px;
margin: 0 auto;
width: 600px;
}
&#footer {
color: $footer-link-color;
font-size: 14px;
text-align: center;
width: 100%;
}
td {
&#body-container {
padding: 20px 40px;
}
}
}
.center {
text-align: center;
}
#logo {
border: none;
outline: none;
min-height: 88px;
width: 134px;
}
#content {
h2 {
color: $header-color;
font-size: 30px;
font-weight: 400;
line-height: 34px;
margin-top: 0;
}
p {
color: $body-color;
font-size: 17px;
line-height: 24px;
margin-bottom: 0;
}
}
#cta {
border: 1px solid $cta-color;
border-radius: 3px;
display: inline-block;
margin: 20px 0;
padding: 12px 24px;
a {
background-color: $message-background-color;
color: $cta-color;
display: inline-block;
text-decoration: none;
}
}
#tanuki {
padding: 40px 0 0;
img {
border: none;
outline: none;
width: 37px;
min-height: 36px;
}
}
#tagline {
font-size: 22px;
font-weight: 100;
padding: 4px 0 40px;
}
#social {
padding: 0 10px 20px;
width: 600px;
word-spacing: 20px;
a {
color: $footer-link-color;
text-decoration: none;
}
}
...@@ -26,8 +26,28 @@ ...@@ -26,8 +26,28 @@
.commit-info-row { .commit-info-row {
margin-bottom: 10px; margin-bottom: 10px;
&.commit-info-row-header {
line-height: 34px;
@media (min-width: $screen-sm-min) {
margin-bottom: 0;
}
.commit-options-dropdown-caret {
@media (max-width: $screen-sm) {
margin-left: 0;
}
}
}
.avatar { .avatar {
@extend .avatar-inline; @extend .avatar-inline;
margin-left: 0;
@media (min-width: $screen-sm-min) {
margin-left: 4px;
}
} }
.commit-committer-link, .commit-committer-link,
.commit-author-link { .commit-author-link {
...@@ -35,10 +55,6 @@ ...@@ -35,10 +55,6 @@
font-weight: bold; font-weight: bold;
} }
.time_ago {
margin-left: 8px;
}
.fa-clipboard { .fa-clipboard {
color: $dropdown-title-btn-color; color: $dropdown-title-btn-color;
} }
......
...@@ -150,6 +150,10 @@ ...@@ -150,6 +150,10 @@
font-weight: 600; font-weight: 600;
} }
.light {
font-weight: normal;
}
.sidebar-collapsed-icon { .sidebar-collapsed-icon {
display: none; display: none;
} }
......
...@@ -40,11 +40,6 @@ ...@@ -40,11 +40,6 @@
} }
} }
.issue-search-form {
margin: 0;
height: 24px;
}
form.edit-issue { form.edit-issue {
margin: 0; margin: 0;
} }
...@@ -96,8 +91,3 @@ form.edit-issue { ...@@ -96,8 +91,3 @@ form.edit-issue {
.issue-form .select2-container { .issue-form .select2-container {
width: 250px !important; width: 250px !important;
} }
.issue-closed-by-widget {
color: $gl-text-color;
margin-left: 52px;
}
...@@ -280,11 +280,5 @@ ...@@ -280,11 +280,5 @@
background-color: $white-light; background-color: $white-light;
color: $gl-placeholder-color; color: $gl-placeholder-color;
} }
th,
td {
padding: 16px;
}
} }
} }
.pipeline-stage { .pipelines {
overflow: hidden; .stage {
text-overflow: ellipsis; max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.duration, .finished_at {
margin: 4px 0;
}
.commit-title {
margin: 0;
}
.controls {
white-space: nowrap;
}
.btn {
margin: 4px;
}
} }
...@@ -66,12 +66,6 @@ ...@@ -66,12 +66,6 @@
} }
} }
.calendar-hint {
margin-top: -12px;
float: right;
font-size: 12px;
}
.profile-link-holder { .profile-link-holder {
display: inline; display: inline;
...@@ -134,14 +128,6 @@ ...@@ -134,14 +128,6 @@
} }
} }
.change-username-title {
color: $gl-warning;
}
.remove-account-title {
color: $gl-danger;
}
.provider-btn-group { .provider-btn-group {
display: inline-block; display: inline-block;
margin-right: 10px; margin-right: 10px;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
margin-bottom: 0; margin-bottom: 0;
} }
.new_project, .new_project,
.edit_project { .edit-project {
fieldset.features { fieldset.features {
.control-label { .control-label {
font-weight: normal; font-weight: normal;
...@@ -26,8 +26,13 @@ ...@@ -26,8 +26,13 @@
} }
.project-home-panel { .project-home-panel {
padding-bottom: 40px; background: $white-light;
border-bottom: 1px solid $border-color; text-align: left;
padding: 24px 0;
.container-fluid {
position: relative;
}
.cover-controls { .cover-controls {
.project-settings-dropdown { .project-settings-dropdown {
...@@ -43,21 +48,55 @@ ...@@ -43,21 +48,55 @@
} }
} }
.project-identicon-holder { .cover-title {
margin-bottom: 16px; margin-bottom: 0;
}
.project-image-container {
@include make-sm-column(1);
max-width: 86px;
min-width: 86px;
padding-right: 0;
margin: 11px 0;
.avatar, .identicon { @media (max-width: $screen-md-max) {
margin: 0 auto; padding-left: 0;
float: none; margin: 0 0 10px;
max-width: none;
min-width: none;
.avatar.s70 {
margin: auto;
}
} }
}
.identicon { .project-info {
@include border-radius(50%); @include make-sm-column(10);
h1 {
font-size: 24px;
font-weight: normal;
margin: 0;
}
.project-home-desc {
p {
margin: 0;
}
} }
} }
.identicon {
float: left;
@include border-radius(50%);
}
.avatar {
float: none;
}
.notifications-btn { .notifications-btn {
margin-top: -28px;
.fa-bell { .fa-bell {
margin-right: 6px; margin-right: 6px;
...@@ -69,28 +108,45 @@ ...@@ -69,28 +108,45 @@
} }
.project-repo-buttons { .project-repo-buttons {
margin-top: 20px; font-size: 0;
margin-bottom: 0;
.count-buttons { .btn {
display: block; @include btn-gray;
margin-bottom: 20px; padding: 3px 10px;
} text-transform: none;
background-color: $background-color;
.clone-row { .fa {
.split-repo-buttons, color: $layout-link-gray;
.project-clone-holder {
display: inline-block;
} }
.split-repo-buttons { .fa-caret-down {
margin: 0 12px; margin-left: 3px;
} }
} }
.btn { .btn-group:not(:first-child):not(:last-child) > .btn {
@include btn-gray; border-top-right-radius: 3px;
text-transform: none; border-bottom-right-radius: 3px;
}
form {
margin-left: 10px;
}
.count-buttons {
display: inline-block;
vertical-align: top;
margin-top: 16px;
}
.project-clone-holder {
display: inline-block;
margin-top: 16px;
input {
height: 29px;
}
} }
.count-with-arrow { .count-with-arrow {
...@@ -140,14 +196,14 @@ ...@@ -140,14 +196,14 @@
line-height: 13px; line-height: 13px;
padding: $gl-vert-padding $gl-padding; padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px; letter-spacing: .4px;
padding: 10px 14px; padding: 7px 14px;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
touch-action: manipulation; touch-action: manipulation;
cursor: pointer; cursor: pointer;
background-image: none; background-image: none;
white-space: nowrap; white-space: nowrap;
margin: 0 11px 0 4px; margin: 0 10px 0 4px;
a { a {
color: inherit; color: inherit;
...@@ -159,6 +215,30 @@ ...@@ -159,6 +215,30 @@
} }
} }
} }
.project-right-buttons {
position: absolute;
right: 16px;
bottom: 0;
.btn {
padding: 3px 10px;
background-color: $background-color;
}
@media (max-width: 1304px) {
top: 0;
}
}
@media (max-width: $screen-md-max) {
text-align: center;
.project-info,
.project-image-container {
width: 100%;
}
}
} }
.split-one { .split-one {
...@@ -289,11 +369,11 @@ a.deploy-project-label { ...@@ -289,11 +369,11 @@ a.deploy-project-label {
} }
.project-stats { .project-stats {
text-align: center;
margin-top: $gl-padding; margin-top: $gl-padding;
margin-bottom: 0; margin-bottom: 0;
padding-top: 10px; padding: 16px 0;
padding-bottom: 4px; background-color: $white-light;
font-size: 0;
ul.nav { ul.nav {
display: inline-block; display: inline-block;
...@@ -304,12 +384,11 @@ a.deploy-project-label { ...@@ -304,12 +384,11 @@ a.deploy-project-label {
} }
.nav > li > a { .nav > li > a {
@include btn-default;
@include btn-gray;
background-color: transparent; background-color: transparent;
border: 1px solid #f7f8fa; margin-right: 12px;
margin-left: 12px; padding: 0 10px;
font-size: 15px;
color: $notes-light-color;
} }
li { li {
...@@ -329,6 +408,10 @@ a.deploy-project-label { ...@@ -329,6 +408,10 @@ a.deploy-project-label {
background-color: #f0f2f5; background-color: #f0f2f5;
} }
} }
&.row-content-block.second-block {
margin-top: 0;
}
} }
pre.light-well { pre.light-well {
...@@ -446,9 +529,14 @@ pre.light-well { ...@@ -446,9 +529,14 @@ pre.light-well {
border-top: 0; border-top: 0;
.edit-project-readme { .edit-project-readme {
z-index: 100; z-index: 2;
position: relative; position: relative;
} }
.wiki h1 {
border-bottom: none;
padding: 0;
}
} }
.git-clone-holder { .git-clone-holder {
......
...@@ -12,3 +12,11 @@ ...@@ -12,3 +12,11 @@
border: 1px solid $warning-message-border; border: 1px solid $warning-message-border;
border-radius: $border-radius-base; border-radius: $border-radius-base;
} }
.warning-title {
color: $gl-warning;
}
.danger-title {
color: $gl-danger;
}
...@@ -16,19 +16,6 @@ ...@@ -16,19 +16,6 @@
} }
} }
.snippet-box {
@include border-radius(2px);
display: block;
float: left;
padding: 0 $gl-padding;
font-weight: normal;
margin-right: 10px;
font-size: $gl-font-size;
border: 1px solid;
line-height: 32px;
}
.markdown-snippet-copy { .markdown-snippet-copy {
position: fixed; position: fixed;
top: -10px; top: -10px;
...@@ -36,3 +23,34 @@ ...@@ -36,3 +23,34 @@
max-height: 0; max-height: 0;
max-width: 0; max-width: 0;
} }
.file-holder.snippet-file-content {
padding-bottom: $gl-padding;
border-bottom: 1px solid $border-color;
.file-title {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
}
.file-actions {
top: 12px;
}
.file-content {
border-left: 1px solid $border-color;
border-right: 1px solid $border-color;
border-bottom: 1px solid $border-color;
}
}
.snippet-title {
font-size: 24px;
font-weight: normal;
}
.snippet-actions {
@media (min-width: $screen-sm-min) {
float: right;
}
}
...@@ -29,6 +29,17 @@ ...@@ -29,6 +29,17 @@
.todo-item { .todo-item {
.todo-title { .todo-title {
@include str-truncated(calc(100% - 174px)); @include str-truncated(calc(100% - 174px));
overflow: visible;
}
.status-box {
margin: 0;
float: none;
display: inline-block;
font-weight: normal;
padding: 0 5px;
line-height: inherit;
font-size: 14px;
} }
.todo-body { .todo-body {
...@@ -76,12 +87,11 @@ ...@@ -76,12 +87,11 @@
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.todo-item { .todo-item {
padding-left: $gl-padding;
.todo-title { .todo-title {
white-space: normal; white-space: normal;
overflow: visible; overflow: visible;
max-width: 100%; max-width: 100%;
margin-bottom: 10px;
} }
.avatar { .avatar {
......
...@@ -31,6 +31,24 @@ class AutocompleteController < ApplicationController ...@@ -31,6 +31,24 @@ class AutocompleteController < ApplicationController
render json: @user, only: [:name, :username, :id], methods: [:avatar_url] render json: @user, only: [:name, :username, :id], methods: [:avatar_url]
end end
def projects
project = Project.find_by_id(params[:project_id])
projects = current_user.authorized_projects
projects = projects.select do |project|
current_user.can?(:admin_issue, project)
end
no_project = {
id: 0,
name_with_namespace: 'No project',
}
projects.unshift(no_project)
projects.delete(project)
render json: projects.to_json(only: [:id, :name_with_namespace], methods: :name_with_namespace)
end
private private
def find_users def find_users
......
...@@ -36,7 +36,7 @@ class JwtController < ApplicationController ...@@ -36,7 +36,7 @@ class JwtController < ApplicationController
end end
def authenticate_project(login, password) def authenticate_project(login, password)
if login == 'gitlab_ci_token' if login == 'gitlab-ci-token'
Project.find_by(builds_enabled: true, runners_token: password) Project.find_by(builds_enabled: true, runners_token: password)
end end
end end
......
...@@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController ...@@ -26,7 +26,7 @@ class Projects::ApplicationController < ApplicationController
project_path = "#{namespace}/#{id}" project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path) @project = Project.find_with_namespace(project_path)
if @project && can?(current_user, :read_project, @project) if can?(current_user, :read_project, @project) && !@project.pending_delete?
if @project.path_with_namespace != project_path if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) redirect_to request.original_url.gsub(project_path, @project.path_with_namespace)
end end
......
...@@ -229,6 +229,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -229,6 +229,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if ci_commit if ci_commit
status = ci_commit.status status = ci_commit.status
coverage = ci_commit.try(:coverage) coverage = ci_commit.try(:coverage)
status ||= "preparing"
else else
ci_service = @merge_request.source_project.ci_service ci_service = @merge_request.source_project.ci_service
status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service
...@@ -238,8 +240,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -238,8 +240,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
status = "preparing" if status.nil?
response = { response = {
title: merge_request.title, title: merge_request.title,
sha: merge_request.last_commit_short_sha, sha: merge_request.last_commit_short_sha,
......
...@@ -74,8 +74,6 @@ class UsersController < ApplicationController ...@@ -74,8 +74,6 @@ class UsersController < ApplicationController
def calendar def calendar
calendar = contributions_calendar calendar = contributions_calendar
@timestamps = calendar.timestamps @timestamps = calendar.timestamps
@starting_year = calendar.starting_year
@starting_month = calendar.starting_month
render 'calendar', layout: false render 'calendar', layout: false
end end
......
...@@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder ...@@ -18,7 +18,7 @@ class GroupProjectsFinder < UnionFinder
projects = [] projects = []
if current_user if current_user
if @group.users.include?(current_user) if @group.users.include?(current_user) || current_user.admin?
projects << @group.projects unless only_shared projects << @group.projects unless only_shared
projects << @group.shared_projects unless only_owned projects << @group.shared_projects unless only_owned
else else
......
...@@ -250,12 +250,12 @@ class IssuableFinder ...@@ -250,12 +250,12 @@ class IssuableFinder
def by_milestone(items) def by_milestone(items)
if milestones? if milestones?
if filter_by_no_milestone? if filter_by_no_milestone?
items = items.where(milestone_id: [-1, nil]) items = items.left_joins_milestones.where(milestone_id: [-1, nil])
elsif filter_by_upcoming_milestone? elsif filter_by_upcoming_milestone?
upcoming_ids = Milestone.upcoming_ids_by_projects(projects) upcoming_ids = Milestone.upcoming_ids_by_projects(projects)
items = items.joins(:milestone).where(milestone_id: upcoming_ids) items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
else else
items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] }) items = items.with_milestone(params[:milestone_title])
if projects if projects
items = items.where(milestones: { project_id: projects }) items = items.where(milestones: { project_id: projects })
......
...@@ -110,8 +110,7 @@ module ApplicationHelper ...@@ -110,8 +110,7 @@ module ApplicationHelper
] ]
# If reference is commit id - we should add it to branch/tag selectbox # If reference is commit id - we should add it to branch/tag selectbox
if(@ref && !options.flatten.include?(@ref) && if @ref && !options.flatten.include?(@ref) && @ref =~ /\A[0-9a-zA-Z]{6,52}\z/
@ref =~ /\A[0-9a-zA-Z]{6,52}\z/)
options << ['Commit', [@ref]] options << ['Commit', [@ref]]
end end
...@@ -263,6 +262,8 @@ module ApplicationHelper ...@@ -263,6 +262,8 @@ module ApplicationHelper
assignee_id: params[:assignee_id], assignee_id: params[:assignee_id],
author_id: params[:author_id], author_id: params[:author_id],
sort: params[:sort], sort: params[:sort],
issue_search: params[:issue_search],
label_name: params[:label_name]
} }
options = exist_opts.merge(options) options = exist_opts.merge(options)
...@@ -273,16 +274,11 @@ module ApplicationHelper ...@@ -273,16 +274,11 @@ module ApplicationHelper
end end
end end
path = request.path params = options.compact
path << "?#{options.to_param}"
if add_label params.delete(:label_name) unless add_label
if params[:label_name].present? and params[:label_name].respond_to?('any?')
params[:label_name].each do |label| "#{request.path}?#{params.to_param}"
path << "&label_name[]=#{label}"
end
end
end
path
end end
def outdated_browser? def outdated_browser?
......
...@@ -123,13 +123,14 @@ module CommitsHelper ...@@ -123,13 +123,14 @@ module CommitsHelper
) )
end end
def revert_commit_link(commit, continue_to_path, btn_class: nil) def revert_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
return unless current_user return unless current_user
tooltip = "Revert this #{commit.change_type_title} in a new merge request" tooltip = "Revert this #{commit.change_type_title} in a new merge request" if has_tooltip
if can_collaborate_with_project? if can_collaborate_with_project?
link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip" btn_class = "btn btn-grouped btn-close btn-#{btn_class}" unless btn_class.nil?
link_to 'Revert', '#modal-revert-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
elsif can?(current_user, :fork_project, @project) elsif can?(current_user, :fork_project, @project)
continue_params = { continue_params = {
to: continue_to_path, to: continue_to_path,
...@@ -140,17 +141,20 @@ module CommitsHelper ...@@ -140,17 +141,20 @@ module CommitsHelper
namespace_key: current_user.namespace.id, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
link_to 'Revert', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
link_to 'Revert', fork_path, class: btn_class, method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
end end
end end
def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil) def cherry_pick_commit_link(commit, continue_to_path, btn_class: nil, has_tooltip: true)
return unless current_user return unless current_user
tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request" tooltip = "Cherry-pick this #{commit.change_type_title} in a new merge request"
if can_collaborate_with_project? if can_collaborate_with_project?
link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: tooltip, class: "btn btn-default btn-grouped btn-#{btn_class} has-tooltip" btn_class = "btn btn-default btn-grouped btn-#{btn_class}" unless btn_class.nil?
link_to 'Cherry-pick', '#modal-cherry-pick-commit', 'data-toggle' => 'modal', 'data-container' => 'body', title: (tooltip if has_tooltip), class: "#{btn_class} #{'has-tooltip' if has_tooltip}"
elsif can?(current_user, :fork_project, @project) elsif can?(current_user, :fork_project, @project)
continue_params = { continue_params = {
to: continue_to_path, to: continue_to_path,
...@@ -161,7 +165,8 @@ module CommitsHelper ...@@ -161,7 +165,8 @@ module CommitsHelper
namespace_key: current_user.namespace.id, namespace_key: current_user.namespace.id,
continue: continue_params) continue: continue_params)
link_to 'Cherry-pick', fork_path, class: 'btn btn-grouped btn-close', method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: tooltip btn_class = "btn btn-grouped btn-close" unless btn_class.nil?
link_to 'Cherry-pick', fork_path, class: "#{btn_class}", method: :post, 'data-toggle' => 'tooltip', 'data-container' => 'body', title: (tooltip if has_tooltip)
end end
end end
......
...@@ -159,28 +159,6 @@ module EventsHelper ...@@ -159,28 +159,6 @@ module EventsHelper
"--broken encoding" "--broken encoding"
end end
def event_to_atom(xml, event)
if event.visible_to_user?(current_user)
xml.entry do
event_link = event_feed_url(event)
event_title = event_feed_title(event)
event_summary = event_feed_summary(event)
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link href: event_link
xml.title truncate(event_title, length: 80)
xml.updated event.created_at.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email))
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
end
xml.summary(type: "xhtml") { |x| x << event_summary unless event_summary.nil? }
end
end
end
def event_row_class(event) def event_row_class(event)
if event.body? if event.body?
"event-block" "event-block"
......
...@@ -13,7 +13,7 @@ module GitlabMarkdownHelper ...@@ -13,7 +13,7 @@ module GitlabMarkdownHelper
def link_to_gfm(body, url, html_options = {}) def link_to_gfm(body, url, html_options = {})
return "" if body.blank? return "" if body.blank?
escaped_body = if body =~ /\A\<img/ escaped_body = if body.start_with?('<img')
body body
else else
escape_once(body) escape_once(body)
......
...@@ -50,14 +50,10 @@ module IssuablesHelper ...@@ -50,14 +50,10 @@ module IssuablesHelper
end end
def user_dropdown_label(user_id, default_label) def user_dropdown_label(user_id, default_label)
return default_label if user_id.nil?
return "Unassigned" if user_id == "0" return "Unassigned" if user_id == "0"
if @project user = User.find_by(id: user_id)
member = @project.team.find_member(user_id)
user = member.user if member
else
user = User.find_by(id: user_id)
end
if user if user
user.name user.name
...@@ -76,7 +72,7 @@ module IssuablesHelper ...@@ -76,7 +72,7 @@ module IssuablesHelper
def issuable_meta(issuable, project, text) def issuable_meta(issuable, project, text)
output = content_tag :strong, "#{text} #{issuable.to_reference}", class: "identifier" output = content_tag :strong, "#{text} #{issuable.to_reference}", class: "identifier"
output << " opened #{time_ago_with_tooltip(issuable.created_at)} by".html_safe output << " opened #{time_ago_with_tooltip(issuable.created_at)} by ".html_safe
output << content_tag(:strong) do output << content_tag(:strong) do
author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs") author_output = link_to_member(project, issuable.author, size: 24, mobile_classes: "hidden-xs")
author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg") author_output << link_to_member(project, issuable.author, size: 24, by_username: true, avatar: false, mobile_classes: "hidden-sm hidden-md hidden-lg")
......
...@@ -105,23 +105,6 @@ module IssuesHelper ...@@ -105,23 +105,6 @@ module IssuesHelper
return 'hidden' if issue.closed? == closed return 'hidden' if issue.closed? == closed
end end
def issue_to_atom(xml, issue)
xml.entry do
xml.id namespace_project_issue_url(issue.project.namespace,
issue.project, issue)
xml.link href: namespace_project_issue_url(issue.project.namespace,
issue.project, issue)
xml.title truncate(issue.title, length: 80)
xml.updated issue.created_at.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email))
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
end
def merge_requests_sentence(merge_requests) def merge_requests_sentence(merge_requests)
# Sorting based on the `!123` or `group/project!123` reference will sort # Sorting based on the `!123` or `group/project!123` reference will sort
# local merge requests first. # local merge requests first.
......
...@@ -48,7 +48,7 @@ module NavHelper ...@@ -48,7 +48,7 @@ module NavHelper
"page-with-layout-nav" if defined?(nav) && nav "page-with-layout-nav" if defined?(nav) && nav
end end
def layout_dropdown_class def nav_control_class
"controls-dropdown-visible" if current_user "nav-control" if current_user
end end
end end
...@@ -144,6 +144,10 @@ module ProjectsHelper ...@@ -144,6 +144,10 @@ module ProjectsHelper
nav_tabs << :merge_requests nav_tabs << :merge_requests
end end
if can?(current_user, :read_pipeline, project)
nav_tabs << :pipelines
end
if can?(current_user, :read_build, project) if can?(current_user, :read_build, project)
nav_tabs << :builds nav_tabs << :builds
end end
......
...@@ -95,7 +95,9 @@ module TabHelper ...@@ -95,7 +95,9 @@ module TabHelper
end end
def project_tab_class def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project) if controller.controller_path.start_with?('projects')
return 'active'
end
if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name
"active" "active"
...@@ -112,7 +114,7 @@ module TabHelper ...@@ -112,7 +114,7 @@ module TabHelper
end end
def profile_tab_class def profile_tab_class
if controller.controller_path =~ /\Aprofiles/ if controller.controller_path.start_with?('profiles')
return 'active' return 'active'
end end
......
...@@ -37,6 +37,16 @@ module TodosHelper ...@@ -37,6 +37,16 @@ module TodosHelper
end end
end end
def todo_target_state_pill(todo)
return unless show_todo_state?(todo)
content_tag(:span, nil, class: 'target-status') do
content_tag(:span, nil, class: "status-box status-box-#{todo.target.state.dasherize}") do
todo.target.state.capitalize
end
end
end
def todos_filter_params def todos_filter_params
{ {
state: params[:state], state: params[:state],
...@@ -95,4 +105,10 @@ module TodosHelper ...@@ -95,4 +105,10 @@ module TodosHelper
options_from_collection_for_select(types, 'name', 'title', params[:type]) options_from_collection_for_select(types, 'name', 'title', params[:type])
end end
private
def show_todo_state?(todo)
(todo.target.is_a?(MergeRequest) || todo.target.is_a?(Issue)) && ['closed', 'merged'].include?(todo.target.state)
end
end end
class DeviseMailer < Devise::Mailer class DeviseMailer < Devise::Mailer
default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>" default from: "#{Gitlab.config.gitlab.email_display_name} <#{Gitlab.config.gitlab.email_from}>"
default reply_to: Gitlab.config.gitlab.email_reply_to default reply_to: Gitlab.config.gitlab.email_reply_to
layout 'devise_mailer'
end end
...@@ -60,6 +60,7 @@ class Ability ...@@ -60,6 +60,7 @@ class Ability
:read_project_member, :read_project_member,
:read_merge_request, :read_merge_request,
:read_note, :read_note,
:read_pipeline,
:read_commit_status, :read_commit_status,
:read_container_image, :read_container_image,
:download_code :download_code
......
...@@ -7,7 +7,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -7,7 +7,7 @@ class ApplicationSetting < ActiveRecord::Base
serialize :restricted_visibility_levels serialize :restricted_visibility_levels
serialize :import_sources serialize :import_sources
serialize :disabled_oauth_sign_in_sources serialize :disabled_oauth_sign_in_sources, Array
serialize :restricted_signup_domains, Array serialize :restricted_signup_domains, Array
attr_accessor :restricted_signup_domains_raw attr_accessor :restricted_signup_domains_raw
......
...@@ -31,18 +31,21 @@ module Issuable ...@@ -31,18 +31,21 @@ module Issuable
scope :unassigned, -> { where("assignee_id IS NULL") } scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_projects, ->(ids) { where(project_id: ids) }
scope :of_milestones, ->(ids) { where(milestone_id: ids) } scope :of_milestones, ->(ids) { where(milestone_id: ids) }
scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) }
scope :opened, -> { with_state(:opened, :reopened) } scope :opened, -> { with_state(:opened, :reopened) }
scope :only_opened, -> { with_state(:opened) } scope :only_opened, -> { with_state(:opened) }
scope :only_reopened, -> { with_state(:reopened) } scope :only_reopened, -> { with_state(:reopened) }
scope :closed, -> { with_state(:closed) } scope :closed, -> { with_state(:closed) }
scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') }
scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") }
scope :order_milestone_due_desc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date DESC') }
scope :order_milestone_due_asc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :join_project, -> { joins(:project) } scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) } scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) } scope :non_archived, -> { join_project.where(projects: { archived: false }) }
scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") }
delegate :name, delegate :name,
:email, :email,
......
...@@ -253,7 +253,7 @@ module Network ...@@ -253,7 +253,7 @@ module Network
leaves = [] leaves = []
leaves.push(commit) if commit.space.zero? leaves.push(commit) if commit.space.zero?
while true loop do
return leaves if commit.parents(@map).count.zero? return leaves if commit.parents(@map).count.zero?
commit = commit.parents(@map).first commit = commit.parents(@map).first
......
...@@ -29,10 +29,17 @@ class Note < ActiveRecord::Base ...@@ -29,10 +29,17 @@ class Note < ActiveRecord::Base
# Attachments are deprecated and are handled by Markdown uploader # Attachments are deprecated and are handled by Markdown uploader
validates :attachment, file_size: { maximum: :max_attachment_size } validates :attachment, file_size: { maximum: :max_attachment_size }
validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' } validates :noteable_type, presence: true
validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' } validates :noteable_id, presence: true, unless: :for_commit?
validates :commit_id, presence: true, if: :for_commit?
validates :author, presence: true validates :author, presence: true
validate unless: :for_commit? do |note|
unless note.noteable.try(:project) == note.project
errors.add(:invalid_project, 'Note and noteable project mismatch')
end
end
mount_uploader :attachment, AttachmentUploader mount_uploader :attachment, AttachmentUploader
# Scopes # Scopes
......
...@@ -431,7 +431,13 @@ class Project < ActiveRecord::Base ...@@ -431,7 +431,13 @@ class Project < ActiveRecord::Base
def check_limit def check_limit
unless creator.can_create_project? or namespace.kind == 'group' unless creator.can_create_project? or namespace.kind == 'group'
self.errors.add(:limit_reached, "Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") projects_limit = creator.projects_limit
if projects_limit == 0
self.errors.add(:limit_reached, "Personal project creation is not allowed. Please contact your administrator with questions")
else
self.errors.add(:limit_reached, "Your project limit is #{projects_limit} projects! Please contact your administrator to increase it")
end
end end
rescue rescue
self.errors.add(:base, "Can't check your ability to create project") self.errors.add(:base, "Can't check your ability to create project")
......
...@@ -35,8 +35,8 @@ class SlackService ...@@ -35,8 +35,8 @@ class SlackService
private private
def message def message
"#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} second(s)" "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
end end
def format(string) def format(string)
Slack::Notifier::LinkFormatter.format(string) Slack::Notifier::LinkFormatter.format(string)
......
...@@ -972,12 +972,6 @@ class Repository ...@@ -972,12 +972,6 @@ class Repository
end end
end end
def main_language
return unless head_exists?
Linguist::Repository.new(rugged, rugged.head.target_id).language
end
def avatar def avatar
return nil unless exists? return nil unless exists?
......
...@@ -6,7 +6,7 @@ module Auth ...@@ -6,7 +6,7 @@ module Auth
return error('not found', 404) unless registry.enabled return error('not found', 404) unless registry.enabled
if params[:offline_token] if params[:offline_token]
return error('unauthorized', 401) unless current_user return error('unauthorized', 401) unless current_user || project
else else
return error('forbidden', 403) unless scope return error('forbidden', 403) unless scope
end end
......
...@@ -53,10 +53,6 @@ class GitPushService < BaseService ...@@ -53,10 +53,6 @@ class GitPushService < BaseService
# could cause the last commit of a merge request to change. # could cause the last commit of a merge request to change.
update_merge_requests update_merge_requests
# Checks if the main language has changed in the project and if so
# it updates it accordingly
update_main_language
perform_housekeeping perform_housekeeping
end end
...@@ -64,19 +60,6 @@ class GitPushService < BaseService ...@@ -64,19 +60,6 @@ class GitPushService < BaseService
@project.repository.copy_gitattributes(params[:ref]) @project.repository.copy_gitattributes(params[:ref])
end end
def update_main_language
# Performance can be bad so for now only check main_language once
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937
return if @project.main_language.present?
return unless is_default_branch?
return unless push_to_new_branch? || push_to_existing_branch?
current_language = @project.repository.main_language
@project.update_attributes(main_language: current_language)
true
end
protected protected
def update_merge_requests def update_merge_requests
......
...@@ -5,8 +5,6 @@ module Notes ...@@ -5,8 +5,6 @@ module Notes
note.author = current_user note.author = current_user
note.system = false note.system = false
return unless valid_project?(note)
if note.save if note.save
# Finish the harder work in the background # Finish the harder work in the background
NewNoteWorker.perform_in(2.seconds, note.id, params) NewNoteWorker.perform_in(2.seconds, note.id, params)
...@@ -15,14 +13,5 @@ module Notes ...@@ -15,14 +13,5 @@ module Notes
note note
end end
private
def valid_project?(note)
return false unless project
return true if note.for_commit?
note.noteable.try(:project) == project
end
end end
end end
...@@ -3,7 +3,7 @@ module Projects ...@@ -3,7 +3,7 @@ module Projects
def execute def execute
new_params = { new_params = {
forked_from_project_id: @project.id, forked_from_project_id: @project.id,
visibility_level: @project.visibility_level, visibility_level: allowed_visibility_level,
description: @project.description, description: @project.description,
name: @project.name, name: @project.name,
path: @project.path, path: @project.path,
...@@ -19,5 +19,17 @@ module Projects ...@@ -19,5 +19,17 @@ module Projects
new_project = CreateService.new(current_user, new_params).execute new_project = CreateService.new(current_user, new_params).execute
new_project new_project
end end
private
def allowed_visibility_level
project_level = @project.visibility_level
if Gitlab::VisibilityLevel.non_restricted_level?(project_level)
project_level
else
Gitlab::VisibilityLevel.highest_allowed_level
end
end
end end
end end
...@@ -47,4 +47,3 @@ ...@@ -47,4 +47,3 @@
= render "admin/builds/build", build: build = render "admin/builds/build", build: build
= paginate @builds, theme: 'gitlab' = paginate @builds, theme: 'gitlab'
...@@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id issues_dashboard_url xml.id issues_dashboard_url
xml.updated @issues.first.created_at.xmlschema if @issues.any? xml.updated @issues.first.created_at.xmlschema if @issues.any?
@issues.each do |issue| xml << render(partial: 'issues/issue', collection: @issues) if @issues.any?
issue_to_atom(xml, issue)
end
end end
...@@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id dashboard_projects_url xml.id dashboard_projects_url
xml.updated @events[0].updated_at.xmlschema if @events[0] xml.updated @events[0].updated_at.xmlschema if @events[0]
@events.each do |event| xml << render(partial: 'events/event', collection: @events) if @events.any?
event_to_atom(xml, event)
end
end end
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
.todo-title.title .todo-title.title
- unless todo.build_failed? - unless todo.build_failed?
= todo_target_state_pill(todo)
%span.author-name %span.author-name
- if todo.author - if todo.author
= link_to_author(todo) = link_to_author(todo)
......
<p>Welcome <%= @resource.name %>!</p>
<% if @resource.unconfirmed_email.present? %>
<p>You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:</p>
<% else %>
<p>You can confirm your account through the link below:</p>
<% end %>
<p><%= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token) %></p>
.center
- if @resource.unconfirmed_email.present?
#content
%h2= @resource.unconfirmed_email
%p Click the link below to confirm your email address.
#cta
= link_to 'Confirm your email address', confirmation_url(@resource, confirmation_token: @token)
- else
#content
- if Gitlab.com?
%h2 Thanks for signing up to GitLab!
- else
%h2 Welcome, #{@resource.name}!
%p To get started, click the link below to confirm your account.
#cta
= link_to 'Confirm your account', confirmation_url(@resource, confirmation_token: @token)
Welcome, <%= @resource.name %>!
<% if @resource.unconfirmed_email.present? %>
You can confirm your email (<%= @resource.unconfirmed_email %>) through the link below:
<% else %>
You can confirm your account through the link below:
<% end %>
<%= confirmation_url(@resource, confirmation_token: @token) %>
%h3.page-title Authorize required %h3.page-title Authorization required
%main{:role => "main"} %main{:role => "main"}
%p.h4 %p.h4
Authorize Authorize
......
return unless event.visible_to_user?(current_user)
xml.entry do
xml.id "tag:#{request.host},#{event.created_at.strftime("%Y-%m-%d")}:#{event.id}"
xml.link href: event_feed_url(event)
xml.title truncate(event_feed_title(event), length: 80)
xml.updated event.created_at.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email))
xml.author do
xml.name event.author_name
xml.email event.author_email
end
xml.summary(type: "xhtml") do |summary|
event_summary = event_feed_summary(event)
summary << event_summary unless event_summary.nil?
end
end
...@@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -6,8 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id issues_group_url xml.id issues_group_url
xml.updated @issues.first.created_at.xmlschema if @issues.any? xml.updated @issues.first.created_at.xmlschema if @issues.any?
@issues.each do |issue| xml << render(partial: 'issues/issue', collection: @issues) if @issues.any?
issue_to_atom(xml, issue)
end
end end
...@@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -6,7 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id group_url(@group) xml.id group_url(@group)
xml.updated @events[0].updated_at.xmlschema if @events[0] xml.updated @events[0].updated_at.xmlschema if @events[0]
@events.each do |event| xml << render(@events) if @events.any?
event_to_atom(xml, event)
end
end end
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
%td.import-target %td.import-target
= repo["path_with_namespace"] = repo["path_with_namespace"]
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import Import
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
......
xml.entry do
xml.id namespace_project_issue_url(issue.project.namespace, issue.project, issue)
xml.link href: namespace_project_issue_url(issue.project.namespace, issue.project, issue)
xml.title truncate(issue.title, length: 80)
xml.updated issue.created_at.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email))
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
end
xml.summary issue.title
end
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
.layout-nav .layout-nav
.container-fluid .container-fluid
= render "layouts/nav/#{nav}" = render "layouts/nav/#{nav}"
.content-wrapper{ class: "#{layout_nav_class} #{layout_dropdown_class}" } .content-wrapper{ class: "#{layout_nav_class}" }
= render "layouts/broadcast" = render "layouts/broadcast"
= render "layouts/flash" = render "layouts/flash"
= yield :flash_message = yield :flash_message
......
!!! 5
%html
%head
%meta(content='text/html; charset=UTF-8' http-equiv='Content-Type')
= stylesheet_link_tag 'mailers/devise'
%body
%table#wrapper
%tr
%td
%table#header
%td{valign: "top"}
= image_tag('mailers/gitlab_header_logo.png', id: 'logo', alt: 'GitLab Wordmark')
%table#body
%tr
%td#body-container
= yield
- if Gitlab.com?
%table#footer
%tr
%td#tanuki
= image_tag('mailers/gitlab_tanuki_2x.png', alt: 'GitLab Logo')
%tr
%td#tagline
Everyone can contribute
%tr
%td#social
= link_to 'Blog', 'https://about.gitlab.com/blog/'
= link_to 'Twitter', 'https://twitter.com/gitlab'
= link_to 'Facebook', 'https://www.facebook.com/gitlab/'
= link_to 'YouTube', 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg'
= link_to 'LinkedIn', 'https://www.linkedin.com/company/gitlab-com'
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
= link_to dashboard_projects_path, title: 'Projects' do = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
= icon('bookmark fw') = icon('bookmark fw')
%span %span
Projects Projects
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
Todos Todos
%span.count.todos-pending-count= number_with_delimiter(todos_pending_count) %span.count.todos-pending-count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do = nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
= icon('dashboard fw') = icon('dashboard fw')
%span %span
Activity Activity
...@@ -26,13 +26,13 @@ ...@@ -26,13 +26,13 @@
%span %span
Milestones Milestones
= nav_link(path: 'dashboard#issues') do = nav_link(path: 'dashboard#issues') do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
= icon('exclamation-circle fw') = icon('exclamation-circle fw')
%span %span
Issues Issues
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count) %span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do = nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
= icon('tasks fw') = icon('tasks fw')
%span %span
Merge Requests Merge Requests
......
= render 'layouts/nav/group_settings' %div{ class: nav_control_class }
= render 'layouts/nav/group_settings'
%ul.nav-links %ul.nav-links.scrolling-tabs
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do .fade-left
= link_to group_path(@group), title: 'Home' do = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= icon('group fw') = link_to group_path(@group), title: 'Home' do
%span = icon('group fw')
Group %span
= nav_link(path: 'groups#activity') do Group
= link_to activity_group_path(@group), title: 'Activity' do = nav_link(path: 'groups#activity') do
= icon('dashboard fw') = link_to activity_group_path(@group), title: 'Activity' do
%span = icon('dashboard fw')
Activity %span
= nav_link(controller: [:group, :milestones]) do Activity
= link_to group_milestones_path(@group), title: 'Milestones' do = nav_link(controller: [:group, :milestones]) do
= icon('clock-o fw') = link_to group_milestones_path(@group), title: 'Milestones' do
%span = icon('clock-o fw')
Milestones %span
= nav_link(path: 'groups#issues') do Milestones
= link_to issues_group_path(@group), title: 'Issues' do = nav_link(path: 'groups#issues') do
= icon('exclamation-circle fw') = link_to issues_group_path(@group), title: 'Issues' do
%span = icon('exclamation-circle fw')
Issues %span
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute Issues
%span.badge.count= number_with_delimiter(issues.count) - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
= nav_link(path: 'groups#merge_requests') do %span.badge.count= number_with_delimiter(issues.count)
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do = nav_link(path: 'groups#merge_requests') do
= icon('tasks fw') = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
%span = icon('tasks fw')
Merge Requests %span
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute Merge Requests
%span.badge.count= number_with_delimiter(merge_requests.count) - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
= nav_link(controller: [:group_members]) do %span.badge.count= number_with_delimiter(merge_requests.count)
= link_to group_group_members_path(@group), title: 'Members' do = nav_link(controller: [:group_members]) do
= icon('users fw') = link_to group_group_members_path(@group), title: 'Members' do
%span = icon('users fw')
Members %span
Members
.fade-right
%ul.nav-links %ul.nav-links.scrolling-tabs
.fade-left
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do = link_to profile_path, title: 'Profile Settings' do
= icon('user fw') = icon('user fw')
...@@ -47,3 +48,4 @@ ...@@ -47,3 +48,4 @@
= icon('history fw') = icon('history fw')
%span %span
Audit Log Audit Log
.fade-right
This diff is collapsed.
%ul.nav.nav-sidebar - if project_nav_tab? :team
= nav_link do = nav_link(controller: [:project_members, :teams]) do
= link_to project_path(@project), title: 'Go to project', class: 'back-link' do = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
= icon('caret-square-o-left fw')
%span %span
Go to project Members
%li.separate-item - if @project.allowed_to_share_with_group?
= nav_link(controller: :group_links) do
%ul.sidebar-subnav = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
= nav_link(path: 'projects#edit') do %span
= link_to edit_project_path(@project), title: 'Project Settings' do Groups
= icon('pencil-square-o fw') = nav_link(controller: :deploy_keys) do
%span = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
Project Settings %span
- if @project.allowed_to_share_with_group? Deploy Keys
= nav_link(controller: :group_links) do = nav_link(controller: :hooks) do
= link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
= icon('share-square-o fw') %span
%span Webhooks
Groups = nav_link(controller: :services) do
= nav_link(controller: :deploy_keys) do = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do %span
= icon('key fw') Services
%span = nav_link(controller: :protected_branches) do
Deploy Keys = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
= nav_link(controller: :hooks) do %span
= link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do Protected Branches
= icon('link fw')
%span
Webhooks
= nav_link(controller: :services) do
= link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
= icon('cogs fw')
%span
Services
= nav_link(controller: :protected_branches) do
= link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
= icon('lock fw')
%span
Protected Branches
- if @project.builds_enabled? - if @project.builds_enabled?
= nav_link(controller: :runners) do = nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
= icon('cog fw') %span
%span Runners
Runners = nav_link(controller: :variables) do
= nav_link(controller: :variables) do = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
= link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do %span
= icon('code fw') Variables
%span = nav_link(controller: :triggers) do
Variables = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
= nav_link(controller: :triggers) do %span
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do Triggers
= icon('retweet fw') = nav_link(controller: :badges) do
%span = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
Triggers %span
= nav_link(controller: :badges) do Badges
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
= icon('star-half-empty fw')
%span
Badges
- page_title @project.name_with_namespace - page_title @project.name_with_namespace
- page_description @project.description unless page_description - page_description @project.description unless page_description
- header_title project_title(@project) unless header_title - header_title project_title(@project) unless header_title
- sidebar "project" unless sidebar - nav "project"
- content_for :scripts_body_top do - content_for :scripts_body_top do
- project = @target_project || @project - project = @target_project || @project
......
- page_title "Settings" - page_title "Settings"
- header_title project_title(@project, "Settings", edit_project_path(@project)) - nav "project"
- sidebar "project_settings"
= render template: "layouts/project" = render template: "layouts/project"
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
- if current_user.can_change_username? - if current_user.can_change_username?
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0.change-username-title %h4.prepend-top-0.warning-title
Change username Change username
%p %p
Changing your username will change path to all personal projects! Changing your username will change path to all personal projects!
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
- if signup_enabled? - if signup_enabled?
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0.remove-account-title %h4.prepend-top-0.danger-title
Remove account Remove account
.col-lg-9 .col-lg-9
- if @user.can_be_removed? - if @user.can_be_removed?
......
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.
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