Commit adc64e45 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

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

parents 99717822 3d009f77
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.9.0 (unreleased) v 8.9.0 (unreleased)
- Allow forking projects with restricted visibility level
- Redesign navigation for project pages - Redesign navigation for project pages
- Fix groups API to list only user's accessible projects - Fix groups API to list only user's accessible projects
- Redesign account and email confirmation emails
- Use gitlab-shell v3.0.0 - Use gitlab-shell v3.0.0
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database - 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) - Changed the Slack build message to use the singular duration if necessary (Aran Koning)
...@@ -39,6 +41,7 @@ v 8.8.0 ...@@ -39,6 +41,7 @@ v 8.8.0
- 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
...@@ -100,6 +103,9 @@ v 8.8.0 ...@@ -100,6 +103,9 @@ v 8.8.0
- 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
......
...@@ -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"
......
...@@ -102,7 +102,6 @@ GEM ...@@ -102,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)
...@@ -790,11 +789,11 @@ GEM ...@@ -790,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)
...@@ -908,7 +907,6 @@ DEPENDENCIES ...@@ -908,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)
...@@ -1043,7 +1041,7 @@ DEPENDENCIES ...@@ -1043,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)
......
...@@ -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
......
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
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)
...@@ -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
*/ */
......
.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;
} }
@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;
...@@ -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 {
...@@ -246,14 +272,18 @@ ...@@ -246,14 +272,18 @@
} }
.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 {
overflow-y: hidden; @include fade(left, rgba(250, 250, 250, 0.4), $background-color);
-webkit-overflow-scrolling: touch; right: 0;
&::-webkit-scrollbar { }
display: none;
.fade-left {
@include fade(right, rgba(250, 250, 250, 0.4), $background-color);
left: 0;
} }
li { li {
...@@ -278,16 +308,39 @@ ...@@ -278,16 +308,39 @@
} }
} }
.nav-control {
.fade-right {
@media (min-width: $screen-xs-max) {
right: 67px;
}
@media (max-width: $screen-xs-min) {
right: 0;
}
}
}
} }
.page-with-layout-nav { .nav-block {
margin-top: 50px; position: relative;
&.controls-dropdown-visible { .nav-links {
@media (max-width: $screen-xs-min) { @include scrolling-links();
margin-top: 96px;
.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;
} }
} }
}
.page-with-layout-nav {
margin-top: $header-height + 2;
.right-sidebar { .right-sidebar {
top: ($header-height * 2) + 2; top: ($header-height * 2) + 2;
......
...@@ -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) {
......
// 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;
}
}
...@@ -91,8 +91,3 @@ form.edit-issue { ...@@ -91,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;
......
...@@ -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
......
...@@ -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"
......
...@@ -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
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
...@@ -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")
......
...@@ -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
<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) %>
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
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'
= 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
...@@ -19,113 +19,117 @@ ...@@ -19,113 +19,117 @@
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave Project Leave Project
%ul.nav-links %div{ class: nav_control_class }
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do %ul.nav-links.scrolling-tabs
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do .fade-left
= icon('bookmark fw') = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
%span = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
Project = icon('bookmark fw')
= nav_link(path: 'projects#activity') do
= link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
= icon('dashboard fw')
%span
Activity
- if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
= link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do
= icon('files-o fw')
%span %span
Files Project
= nav_link(path: 'projects#activity') do
- if project_nav_tab? :commits = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
= nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do = icon('dashboard fw')
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
= icon('history fw')
%span %span
Commits Activity
- if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
= link_to project_files_path(@project), title: 'Files', class: 'shortcuts-tree' do
= icon('files-o fw')
%span
Files
- if project_nav_tab? :pipelines - if project_nav_tab? :commits
= nav_link(controller: :pipelines) do = nav_link(controller: %w(commit commits compare repositories tags branches releases network)) do
= link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
= icon('ship fw') = icon('history fw')
%span %span
Pipelines Commits
%span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
- if project_nav_tab? :builds - if project_nav_tab? :pipelines
= nav_link(controller: %w(builds)) do = nav_link(controller: :pipelines) do
= link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
= icon('cubes fw') = icon('ship fw')
%span %span
Builds Pipelines
%span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
- if project_nav_tab? :container_registry - if project_nav_tab? :builds
= nav_link(controller: %w(container_registry)) do = nav_link(controller: %w(builds)) do
= link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do
= icon('hdd-o fw') = icon('cubes fw')
%span %span
Container Registry Builds
%span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
- if project_nav_tab? :graphs - if project_nav_tab? :container_registry
= nav_link(controller: %w(graphs)) do = nav_link(controller: %w(container_registry)) do
= link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
= icon('area-chart fw') = icon('hdd-o fw')
%span %span
Graphs Container Registry
- if project_nav_tab? :milestones - if project_nav_tab? :graphs
= nav_link(controller: :milestones) do = nav_link(controller: %w(graphs)) do
= link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do = link_to namespace_project_graph_path(@project.namespace, @project, current_ref), title: 'Graphs', class: 'shortcuts-graphs' do
= icon('clock-o fw') = icon('area-chart fw')
%span %span
Milestones Graphs
- if project_nav_tab? :issues - if project_nav_tab? :milestones
= nav_link(controller: :issues) do = nav_link(controller: :milestones) do
= link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do
= icon('exclamation-circle fw') = icon('clock-o fw')
%span %span
Issues Milestones
- if @project.default_issues_tracker?
%span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
- if project_nav_tab? :merge_requests - if project_nav_tab? :issues
= nav_link(controller: :merge_requests) do = nav_link(controller: :issues) do
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues' do
= icon('tasks fw') = icon('exclamation-circle fw')
%span %span
Merge Requests Issues
%span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) - if @project.default_issues_tracker?
%span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
- if project_nav_tab? :labels - if project_nav_tab? :merge_requests
= nav_link(controller: :labels) do = nav_link(controller: :merge_requests) do
= link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= icon('tags fw') = icon('tasks fw')
%span %span
Labels Merge Requests
%span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
- if project_nav_tab? :wiki - if project_nav_tab? :labels
= nav_link(controller: :wikis) do = nav_link(controller: :labels) do
= link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do
= icon('book fw') = icon('tags fw')
%span %span
Wiki Labels
- if project_nav_tab? :snippets - if project_nav_tab? :wiki
= nav_link(controller: :snippets) do = nav_link(controller: :wikis) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
= icon('clipboard fw') = icon('book fw')
%span %span
Snippets Wiki
- if project_nav_tab? :snippets
= nav_link(controller: :snippets) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
= icon('clipboard fw')
%span
Snippets
-# Global shortcut to network page for compatibility
- if project_nav_tab? :network
%li.hidden
= link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do
Network
-# Global shortcut to network page for compatibility -# Shortcut to create a new issue
- if project_nav_tab? :network
%li.hidden %li.hidden
= link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network' do = link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do
Network Create a new issue
-# Shortcut to create a new issue .fade-right
%li.hidden
= link_to new_namespace_project_issue_path(@project.namespace, @project), class: 'shortcuts-new-issue' do
Create a new issue
...@@ -35,9 +35,6 @@ ...@@ -35,9 +35,6 @@
= icon('wrench') = icon('wrench')
%span CI Lint %span CI Lint
.row-content-block
#{(@scope || 'all').capitalize} builds from this project
%ul.content-list %ul.content-list
- if @builds.blank? - if @builds.blank?
%li %li
......
...@@ -57,14 +57,10 @@ ...@@ -57,14 +57,10 @@
%td.duration %td.duration
- if build.duration - if build.duration
= icon("clock-o")
&nbsp;
#{duration_in_words(build.finished_at, build.started_at)} #{duration_in_words(build.finished_at, build.started_at)}
%td.timestamp %td.timestamp
- if build.finished_at - if build.finished_at
= icon("calendar")
&nbsp;
%span #{time_ago_with_tooltip(build.finished_at)} %span #{time_ago_with_tooltip(build.finished_at)}
- if defined?(coverage) && coverage - if defined?(coverage) && coverage
......
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
&middot; &middot;
= link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace" = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace"
&nbsp; &nbsp;
- if commit.latest?
%span.label.label-success latest
- if commit.tag? - if commit.tag?
%span.label.label-primary tag %span.label.label-primary tag
- elsif commit.latest?
%span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest
- if commit.triggered? - if commit.triggered?
%span.label.label-primary triggered %span.label.label-primary triggered
- if commit.yaml_errors.present? - if commit.yaml_errors.present?
...@@ -23,33 +23,29 @@ ...@@ -23,33 +23,29 @@
- if commit.builds.any?(&:stuck?) - if commit.builds.any?(&:stuck?)
%span.label.label-warning stuck %span.label.label-warning stuck
%p %p.commit-title
%span - if commit_data = commit.commit_data
- if commit_data = commit.commit_data = link_to_gfm truncate(commit_data.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message"
= link_to_gfm commit_data.title, namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message" - else
- else Cant find HEAD commit for this branch
Cant find HEAD commit for this branch
- stages_status = commit.statuses.stages_status - stages_status = commit.statuses.stages_status
- stages.each do |stage| - stages.each do |stage|
%td %td
- if status = stages_status[stage] - status = stages_status[stage]
- tooltip = "#{stage.titleize}: #{status}" - tooltip = "#{stage.titleize}: #{status || 'not found'}"
%span.has-tooltip{ title: "#{tooltip}", class: "ci-status-icon-#{status}" } - if status
= link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do
= ci_icon_for_status(status) = ci_icon_for_status(status)
- else
.light.has-tooltip{ title: tooltip }
\-
%td %td
- if commit.started_at && commit.finished_at - if commit.started_at && commit.finished_at
%p %p.duration
= icon("clock-o")
&nbsp;
#{duration_in_words(commit.finished_at, commit.started_at)} #{duration_in_words(commit.finished_at, commit.started_at)}
- if commit.finished_at
%p
= icon("calendar")
&nbsp;
#{time_ago_with_tooltip(commit.finished_at)}
%td %td
.controls.hidden-xs.pull-right .controls.hidden-xs.pull-right
...@@ -67,11 +63,9 @@ ...@@ -67,11 +63,9 @@
%span #{build.name} %span #{build.name}
- if can?(current_user, :update_pipeline, @project) - if can?(current_user, :update_pipeline, @project)
&nbsp;
- if commit.retryable? && commit.builds.failed.any? - if commit.retryable? && commit.builds.failed.any?
= link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn has-tooltip', title: "Retry", method: :post do
= icon("repeat") = icon("repeat")
&nbsp;
- if commit.active? - if commit.active?
= link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
= icon("remove") = icon("remove")
%tr %tr
%th{colspan: 10} %th{colspan: 10}
%strong %strong
%a{name: stage}
- status = statuses.latest.status - status = statuses.latest.status
%span{class: "ci-status-link ci-status-icon-#{status}"} %span{class: "ci-status-link ci-status-icon-#{status}"}
= ci_icon_for_status(status) = ci_icon_for_status(status)
......
xml.entry do
xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id)
xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id)
xml.title truncate(commit.title, length: 80)
xml.updated commit.committed_date.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email))
xml.author do |author|
xml.name commit.author_name
xml.email commit.author_email
end
xml.summary markdown(commit.description, pipeline: :single_line)
end
...@@ -6,18 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear ...@@ -6,18 +6,5 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.id namespace_project_commits_url(@project.namespace, @project, @ref) xml.id namespace_project_commits_url(@project.namespace, @project, @ref)
xml.updated @commits.first.committed_date.xmlschema if @commits.any? xml.updated @commits.first.committed_date.xmlschema if @commits.any?
@commits.each do |commit| xml << render(@commits) if @commits.any?
xml.entry do
xml.id namespace_project_commit_url(@project.namespace, @project, id: commit.id)
xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id)
xml.title truncate(commit.title, length: 80)
xml.updated commit.committed_date.xmlschema
xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email))
xml.author do |author|
xml.name commit.author_name
xml.email commit.author_email
end
xml.summary markdown(commit.description, pipeline: :single_line)
end
end
end end
...@@ -50,14 +50,10 @@ ...@@ -50,14 +50,10 @@
%td.duration %td.duration
- if generic_commit_status.duration - if generic_commit_status.duration
= icon("clock-o")
&nbsp;
#{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)} #{duration_in_words(generic_commit_status.finished_at, generic_commit_status.started_at)}
%td.timestamp %td.timestamp
- if generic_commit_status.finished_at - if generic_commit_status.finished_at
= icon("calendar")
&nbsp;
%span #{time_ago_with_tooltip(generic_commit_status.finished_at)} %span #{time_ago_with_tooltip(generic_commit_status.finished_at)}
- if defined?(coverage) && coverage - if defined?(coverage) && coverage
......
...@@ -24,5 +24,8 @@ ...@@ -24,5 +24,8 @@
MERGED MERGED
- elsif merge_request.closed? - elsif merge_request.closed?
CLOSED CLOSED
- if @closed_by_merge_requests.present? %li
= render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count} = render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
- if @closed_by_merge_requests.present?
%li
= render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
...@@ -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 namespace_project_issues_url(@project.namespace, @project) xml.id namespace_project_issues_url(@project.namespace, @project)
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
...@@ -36,15 +36,7 @@ ...@@ -36,15 +36,7 @@
= icon('wrench') = icon('wrench')
%span CI Lint %span CI Lint
.row-content-block %ul.content-list.pipelines
- if @scope == 'running'
Running pipelines for this project
- elsif @scope.nil?
Pipelines for this project
- else
#{@scope.titleize} for this project
%ul.content-list
- stages = @pipelines.stages - stages = @pipelines.stages
- if @pipelines.blank? - if @pipelines.blank?
%li %li
...@@ -56,10 +48,10 @@ ...@@ -56,10 +48,10 @@
%th ID %th ID
%th Commit %th Commit
- stages.each do |stage| - stages.each do |stage|
%th %th.stage
%span.pipeline-stage.has-tooltip{ title: "#{stage.titleize}" } %span.has-tooltip{ title: "#{stage.titleize}" }
= stage.titleize.pluralize = stage.titleize.pluralize
%th %th Duration
%th %th
= render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages = render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages
......
...@@ -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 namespace_project_url(@project.namespace, @project) xml.id namespace_project_url(@project.namespace, @project)
xml.updated @events[0].updated_at.xmlschema if @events[0] xml.updated @events[0].updated_at.xmlschema if @events[0]
@events.each do |event| xml << render(@events) if @events.any?
event_to_atom(xml, event)
end
end end
%ul.nav-links.event-filter %ul.nav-links.event-filter.scrolling-tabs
.fade-left
= event_filter_link EventFilter.push, 'Push events' = event_filter_link EventFilter.push, 'Push events'
= event_filter_link EventFilter.merged, 'Merge events' = event_filter_link EventFilter.merged, 'Merge events'
= event_filter_link EventFilter.comments, 'Comments' = event_filter_link EventFilter.comments, 'Comments'
= event_filter_link EventFilter.team, 'Team' = event_filter_link EventFilter.team, 'Team'
.fade-right
#cal-heatmap.calendar .clearfix.calendar
:javascript .js-contrib-calendar
new Calendar( .calendar-hint
#{@timestamps.to_json}, Summary of issues, merge requests, and push events
#{@starting_year}, :javascript
#{@starting_month}, new Calendar(
'#{user_calendar_activities_path}' #{@timestamps.to_json},
); '#{user_calendar_activities_path}'
);
.calendar-hint Summary of issues, merge requests, and push events
%h4.prepend-top-20 %h4.prepend-top-20
%span.light Contributions for Contributions for
%strong #{@calendar_date.to_s(:short)} %strong #{@calendar_date.to_s(:short)}
%ul.bordered-list - if @events.any?
- @events.sort_by(&:created_at).each do |event| %ul.bordered-list
%li - @events.sort_by(&:created_at).each do |event|
%span.light %li
%i.fa.fa-clock-o %span.light
= event.created_at.to_s(:time) %i.fa.fa-clock-o
- if event.push? = event.created_at.to_s(:time)
#{event.action_name} #{event.ref_type} #{event.ref_name} - if event.push?
- else #{event.action_name} #{event.ref_type} #{event.ref_name}
= event_action_name(event)
- if event.target
%strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
at
%strong
- if event.project
= link_to_project event.project
- else - else
= event.project_name = event_action_name(event)
- if event.target
%strong= link_to "##{event.target_iid}", [event.project.namespace.becomes(Namespace), event.project, event.target]
at
%strong
- if event.project
= link_to_project event.project
- else
= event.project_name
- else
%p
No contributions found for #{@calendar_date.to_s(:short)}
...@@ -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 user_url(@user) xml.id user_url(@user)
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
...@@ -89,10 +89,9 @@ ...@@ -89,10 +89,9 @@
.tab-content .tab-content
#activity.tab-pane #activity.tab-pane
.row-content-block.calender-block.white.second-block.hidden-xs .row-content-block.calender-block.white.second-block.hidden-xs
%div{ class: container_class } .user-calendar{data: {href: user_calendar_path}}
.user-calendar{data: {href: user_calendar_path}} %h4.center.light
%h4.center.light %i.fa.fa-spinner.fa-spin
%i.fa.fa-spinner.fa-spin
.user-calendar-activities .user-calendar-activities
.content_list{ data: {href: user_path} } .content_list{ data: {href: user_path} }
......
...@@ -80,7 +80,7 @@ module Gitlab ...@@ -80,7 +80,7 @@ module Gitlab
config.assets.precompile << "*.png" config.assets.precompile << "*.png"
config.assets.precompile << "print.css" config.assets.precompile << "print.css"
config.assets.precompile << "notify.css" config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/repository_push_email.css" config.assets.precompile << "mailers/*.css"
# Version of your assets, change this if you want to expire all your assets # Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0' config.assets.version = '1.0'
......
...@@ -39,6 +39,7 @@ Rails.application.configure do ...@@ -39,6 +39,7 @@ Rails.application.configure do
config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.delivery_method = :letter_opener_web
# Don't make a mess when bootstrapping a development environment # Don't make a mess when bootstrapping a development environment
config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1') config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1')
config.action_mailer.preview_path = 'spec/mailers/previews'
config.eager_load = false config.eager_load = false
end end
...@@ -3,6 +3,6 @@ Premailer::Rails.config.merge!( ...@@ -3,6 +3,6 @@ Premailer::Rails.config.merge!(
generate_text_part: false, generate_text_part: false,
preserve_styles: true, preserve_styles: true,
remove_comments: true, remove_comments: true,
remove_ids: true, remove_ids: false,
remove_scripts: false remove_scripts: false
) )
...@@ -19,6 +19,8 @@ Components/Servers Required: ...@@ -19,6 +19,8 @@ Components/Servers Required:
- 2 servers/virtual machines (one active/one passive) - 2 servers/virtual machines (one active/one passive)
![Active/Passive HA Diagram](../img/high_availability/active-passive-diagram.png)
### Active/Active ### Active/Active
This architecture scales easily because all application servers handle This architecture scales easily because all application servers handle
...@@ -26,6 +28,8 @@ user requests simultaneously. The database, Redis, and GitLab application are ...@@ -26,6 +28,8 @@ user requests simultaneously. The database, Redis, and GitLab application are
all deployed on separate servers. The configuration is **only** highly-available all deployed on separate servers. The configuration is **only** highly-available
if the database, Redis and storage are also configured as such. if the database, Redis and storage are also configured as such.
![Active/Active HA Diagram](../img/high_availability/active-active-diagram.png)
**Steps to configure active/active:** **Steps to configure active/active:**
1. [Configure the database](database.md) 1. [Configure the database](database.md)
......
...@@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps ...@@ -34,7 +34,7 @@ class Spinach::Features::User < Spinach::FeatureSteps
end end
step 'I should see contributions calendar' do step 'I should see contributions calendar' do
expect(page).to have_css('.cal-heatmap-container') expect(page).to have_css('.js-contrib-calendar')
end end
def contributed_project def contributed_project
......
...@@ -19,7 +19,7 @@ module Gitlab ...@@ -19,7 +19,7 @@ module Gitlab
select('date(created_at) as date, count(id) as total_amount'). select('date(created_at) as date, count(id) as total_amount').
map(&:attributes) map(&:attributes)
dates = (1.year.ago.to_date..(Date.today + 1.day)).to_a dates = (1.year.ago.to_date..Date.today).to_a
dates.each do |date| dates.each do |date|
date_id = date.to_time.to_i.to_s date_id = date.to_time.to_i.to_s
......
...@@ -7,7 +7,7 @@ module Gitlab ...@@ -7,7 +7,7 @@ module Gitlab
end end
def initialize(url, credentials: nil) def initialize(url, credentials: nil)
@url = Addressable::URI.parse(URI.encode(url)) @url = Addressable::URI.parse(url)
@credentials = credentials @credentials = credentials
end end
......
...@@ -32,6 +32,13 @@ module Gitlab ...@@ -32,6 +32,13 @@ module Gitlab
} }
end end
def highest_allowed_level
restricted_levels = current_application_settings.restricted_visibility_levels
allowed_levels = self.values - restricted_levels
allowed_levels.max || PRIVATE
end
def allowed_for?(user, level) def allowed_for?(user, level)
user.is_admin? || allowed_level?(level.to_i) user.is_admin? || allowed_level?(level.to_i)
end end
......
...@@ -43,7 +43,6 @@ describe "Builds" do ...@@ -43,7 +43,6 @@ describe "Builds" do
end end
it { expect(page).to have_selector('.nav-links li.active', text: 'All') } it { expect(page).to have_selector('.nav-links li.active', text: 'All') }
it { expect(page).to have_selector('.row-content-block', text: 'All builds from this project') }
it { expect(page).to have_content @build.short_sha } it { expect(page).to have_content @build.short_sha }
it { expect(page).to have_content @build.ref } it { expect(page).to have_content @build.ref }
it { expect(page).to have_content @build.name } it { expect(page).to have_content @build.name }
......
...@@ -186,7 +186,7 @@ describe 'Filter issues', feature: true do ...@@ -186,7 +186,7 @@ describe 'Filter issues', feature: true do
fill_in 'issue_search', with: 'testing' fill_in 'issue_search', with: 'testing'
page.within '.issues-list' do page.within '.issues-list' do
expect(page).to_not have_selector('.issue') expect(page).not_to have_selector('.issue')
end end
end end
end end
......
class DeviseMailerPreview < ActionMailer::Preview
def confirmation_instructions_for_signup
user = User.new(name: 'Jane Doe', email: 'signup@example.com')
DeviseMailer.confirmation_instructions(user, 'faketoken', {})
end
def confirmation_instructions_for_new_email
user = User.last
DeviseMailer.confirmation_instructions(user, 'faketoken', {})
end
end
...@@ -60,7 +60,7 @@ describe Project, models: true do ...@@ -60,7 +60,7 @@ describe Project, models: true do
project2 = build(:project) project2 = build(:project)
allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object) allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
expect(project2).not_to be_valid expect(project2).not_to be_valid
expect(project2.errors[:limit_reached].first).to match(/Your project limit is 0/) expect(project2.errors[:limit_reached].first).to match(/Personal project creation is not allowed/)
end end
end end
......
...@@ -42,6 +42,33 @@ describe Projects::ForkService, services: true do ...@@ -42,6 +42,33 @@ describe Projects::ForkService, services: true do
expect(@to_project.builds_enabled?).to be_truthy expect(@to_project.builds_enabled?).to be_truthy
end end
end end
context "when project has restricted visibility level" do
context "and only one visibility level is restricted" do
before do
@from_project.update_attributes(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::INTERNAL])
end
it "creates fork with highest allowed level" do
forked_project = fork_project(@from_project, @to_user)
expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
end
end
context "and all visibility levels are restricted" do
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC, Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PRIVATE])
end
it "creates fork with private visibility levels" do
forked_project = fork_project(@from_project, @to_user)
expect(forked_project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
end
end end
describe :fork_to_namespace do describe :fork_to_namespace do
......
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