Commit 768721dc authored by Tomasz Maczukin's avatar Tomasz Maczukin

Merge branch 'master' into ci/api-triggers

* master: (150 commits)
  fixes margin and padding
  Update mailroom/postfix documentation [ci skip]
  Fix css mess around git clone panel. Align it properly
  Fix missing padding for user/group pages
  Fix parse_gollum_tags matcher
  Update documentation on Banzai::Filter::GollumTagsFilter
  Add tests for the wiki pipeline
  Refactoring Banzai::Filter::GollumTagsFilter
  Make sure the .git is at the end on Gitlab::GithubImport::WikiFormatter
  Remove GollumTagsPipeline
  Refactoring Gitlab::GithubImport::Importer
  Remove unnecessary brackets on WIKI_SLUG_ID route constraints
  Move js function to removing accents to vendor/assets/javascripts
  Update CHANGELOG
  Use the WikiPipeline when rendering the wiki markdown content
  Add Banzai::Filter::GollumTagsFilter for parsing Gollum's tags in HTML
  Relax constraints for wiki slug
  Import GitHub wiki into GitLab
  Move Ci::Build#available_statuses to AVAILABLE_STATUSES constant in CommitStatus
  Revert changes to how the notes are paginated in the API
  ...

Conflicts:
	doc/api/README.md
	lib/api/entities.rb
parents 7ed5bc5c 2f2aada3
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.5.0 (unreleased)
- Remove gray background from layout in UI
v 8.4.0 (unreleased) v 8.4.0 (unreleased)
- Add pagination headers to already paginated API resources
- Properly generate diff of orphan commits, like the first commit in a repository
- Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages - Improve the consistency of commit titles, branch names, tag names, issue/MR titles, on their respective project pages
- Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse) - Autocomplete data is now always loaded, instead of when focusing a comment text area (Yorick Peterse)
- Improved performance of finding issues for an entire group (Yorick Peterse) - Improved performance of finding issues for an entire group (Yorick Peterse)
...@@ -47,10 +52,15 @@ v 8.4.0 (unreleased) ...@@ -47,10 +52,15 @@ v 8.4.0 (unreleased)
- Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee) - Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee)
- Add API support for managing project's build triggers - Add API support for managing project's build triggers
- Add API support for managing project's build variables - Add API support for managing project's build variables
- Add API support for managing builds of a project
- Add API support for managing build variables of project
- Allow broadcast messages to be edited - Allow broadcast messages to be edited
- Autosize Markdown textareas
- Import GitHub wiki into GitLab
v 8.3.4 v 8.3.4
- Use gitlab-workhorse 0.5.4 (fixes API routing bug) - Use gitlab-workhorse 0.5.4 (fixes API routing bug)
- Add build artifacts browser
v 8.3.3 v 8.3.3
- Preserve CE behavior with JIRA integration by only calling API if URL is set - Preserve CE behavior with JIRA integration by only calling API if URL is set
...@@ -84,6 +94,7 @@ v 8.3.0 ...@@ -84,6 +94,7 @@ v 8.3.0
- Add open_issues_count to project API (Stan Hu) - Add open_issues_count to project API (Stan Hu)
- Expand character set of usernames created by Omniauth (Corey Hinshaw) - Expand character set of usernames created by Omniauth (Corey Hinshaw)
- Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
- Add unsubscribe link in the email footer (Zeger-Jan van de Weg)
- Provide better diagnostic message upon project creation errors (Stan Hu) - Provide better diagnostic message upon project creation errors (Stan Hu)
- Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu) - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu)
- Remove api credentials from link to build_page - Remove api credentials from link to build_page
......
class @Activities class @Activities
constructor: -> constructor: ->
Pager.init 20, true Pager.init 20, true
$(".event-filter .btn").bind "click", (event) => $(".event-filter a").bind "click", (event) =>
event.preventDefault() event.preventDefault()
@toggleFilter($(event.currentTarget)) @toggleFilter($(event.currentTarget))
@reloadActivities() @reloadActivities()
...@@ -12,7 +12,7 @@ class @Activities ...@@ -12,7 +12,7 @@ class @Activities
toggleFilter: (sender) -> toggleFilter: (sender) ->
sender.toggleClass "active" sender.closest('li').toggleClass "active"
event_filters = $.cookie("event_filter") event_filters = $.cookie("event_filter")
filter = sender.attr("id").split("_")[0] filter = sender.attr("id").split("_")[0]
if event_filters if event_filters
......
#= require autosize
$ ->
autosize($('.js-autosize'))
...@@ -48,15 +48,16 @@ class @MergeRequest ...@@ -48,15 +48,16 @@ class @MergeRequest
_this = @ _this = @
$('a.btn-close, a.btn-reopen').on 'click', (e) -> $('a.btn-close, a.btn-reopen').on 'click', (e) ->
$this = $(this) $this = $(this)
if $this.data('submitted') shouldSubmit = $this.hasClass('btn-comment')
if shouldSubmit && $this.data('submitted')
return return
if shouldSubmit
if $this.hasClass('btn-comment-and-close') || $this.hasClass('btn-comment-and-reopen')
e.preventDefault() e.preventDefault()
e.stopImmediatePropagation() e.stopImmediatePropagation()
shouldSubmit = $this.hasClass('btn-comment')
console.log("shouldSubmit")
if shouldSubmit
_this.submitNoteForm($this.closest('form'),$this) _this.submitNoteForm($this.closest('form'),$this)
submitNoteForm: (form, $button) => submitNoteForm: (form, $button) =>
noteText = form.find("textarea.js-note-text").val() noteText = form.find("textarea.js-note-text").val()
if noteText.trim().length > 0 if noteText.trim().length > 0
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# #
# ### Example Markup # ### Example Markup
# #
# <ul class="nav nav-tabs merge-request-tabs"> # <ul class="nav-links merge-request-tabs">
# <li class="notes-tab active"> # <li class="notes-tab active">
# <a data-action="notes" data-target="#notes" data-toggle="tab" href="/foo/bar/merge_requests/1"> # <a data-action="notes" data-target="#notes" data-toggle="tab" href="/foo/bar/merge_requests/1">
# Discussion # Discussion
......
#= require autosave #= require autosave
#= require autosize
#= require dropzone #= require dropzone
#= require dropzone_input #= require dropzone_input
#= require gfm_auto_complete #= require gfm_auto_complete
...@@ -246,6 +247,7 @@ class @Notes ...@@ -246,6 +247,7 @@ class @Notes
else else
previewButton.removeClass("turn-on").addClass "turn-off" previewButton.removeClass("turn-on").addClass "turn-off"
autosize(textarea)
new Autosave textarea, [ new Autosave textarea, [
"Note" "Note"
form.find("#note_commit_id").val() form.find("#note_commit_id").val()
...@@ -521,9 +523,13 @@ class @Notes ...@@ -521,9 +523,13 @@ class @Notes
if textarea.val().trim().length > 0 if textarea.val().trim().length > 0
form.find('.js-note-target-reopen').text('Comment & reopen') form.find('.js-note-target-reopen').text('Comment & reopen')
form.find('.js-note-target-close').text('Comment & close') form.find('.js-note-target-close').text('Comment & close')
form.find('.js-note-target-reopen').addClass('btn-comment-and-reopen')
form.find('.js-note-target-close').addClass('btn-comment-and-close')
else else
form.find('.js-note-target-reopen').text('Reopen') form.find('.js-note-target-reopen').text('Reopen')
form.find('.js-note-target-close').text('Close') form.find('.js-note-target-close').text('Close')
form.find('.js-note-target-reopen').removeClass('btn-comment-and-reopen')
form.find('.js-note-target-close').removeClass('btn-comment-and-close')
initTaskList: -> initTaskList: ->
@enableTaskList() @enableTaskList()
......
#= require latinise
class @Wikis class @Wikis
constructor: -> constructor: ->
$('.build-new-wiki').bind "click", (e) -> $('.build-new-wiki').bind 'click', (e) =>
$('[data-error~=slug]').addClass("hidden") $('[data-error~=slug]').addClass('hidden')
$('p.hint').show()
field = $('#new_wiki_path') field = $('#new_wiki_path')
valid_slug_pattern = /^[\w\/-]+$/ slug = @slugify(field.val())
slug = field.val() if (slug.length > 0)
if slug.match valid_slug_pattern
path = field.attr('data-wikis-path') path = field.attr('data-wikis-path')
if(slug.length > 0) location.href = path + '/' + slug
location.href = path + "/" + slug
else dasherize: (value) ->
e.preventDefault() value.replace(/[_\s]+/g, '-')
$('p.hint').hide()
$('[data-error~=slug]').removeClass("hidden") slugify: (value) =>
@dasherize(value.trim().toLowerCase().latinise())
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
@import "framework/lists.scss"; @import "framework/lists.scss";
@import "framework/markdown_area.scss"; @import "framework/markdown_area.scss";
@import "framework/mobile.scss"; @import "framework/mobile.scss";
@import "framework/nav.scss";
@import "framework/pagination.scss"; @import "framework/pagination.scss";
@import "framework/panels.scss"; @import "framework/panels.scss";
@import "framework/selects.scss"; @import "framework/selects.scss";
......
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
line-height: 36px; line-height: 36px;
} }
.content-block,
.gray-content-block { .gray-content-block {
margin: -$gl-padding; margin-top: 0;
margin-bottom: -$gl-padding;
background-color: $background-color; background-color: $background-color;
padding: $gl-padding; padding: $gl-padding;
margin-bottom: 0px; margin-bottom: 0px;
...@@ -86,10 +86,7 @@ ...@@ -86,10 +86,7 @@
.cover-block { .cover-block {
text-align: center; text-align: center;
background: $background-color; background: $background-color;
margin: -$gl-padding; padding-top: 44px;
margin-bottom: 0;
padding: 44px $gl-padding;
border-bottom: 1px solid $border-color;
position: relative; position: relative;
.avatar-holder { .avatar-holder {
...@@ -136,3 +133,19 @@ ...@@ -136,3 +133,19 @@
.block-connector { .block-connector {
margin-top: -1px; margin-top: -1px;
} }
.nav-block {
.controls {
float: right;
margin-top: 11px;
}
}
.content-block {
padding: $gl-padding 0;
border-bottom: 1px solid $border-color;
&.oneline-block {
line-height: 42px;
}
}
@mixin btn-default { @mixin btn-default {
@include border-radius(3px); @include border-radius(3px);
border-width: 1px; font-size: $gl-font-size;
border-style: solid;
font-size: 15px;
font-weight: 500; font-weight: 500;
line-height: 18px; padding: $gl-vert-padding $gl-padding;
padding: 11px $gl-padding;
letter-spacing: .4px;
&:focus, &:focus,
&:active { &:active {
...@@ -17,8 +13,6 @@ ...@@ -17,8 +13,6 @@
@mixin btn-middle { @mixin btn-middle {
@include btn-default; @include btn-default;
@include border-radius(3px);
padding: 11px 24px;
} }
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) { @mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
...@@ -74,16 +68,15 @@ ...@@ -74,16 +68,15 @@
@include btn-default; @include btn-default;
@include btn-white; @include btn-white;
&.btn-small,
&.btn-sm { &.btn-sm {
padding: 5px 10px; padding: 4px 10px;
} font-size: 13px;
line-height: 18px;
&.btn-nr {
padding: 7px 10px;
} }
&.btn-xs { &.btn-xs {
padding: 1px 5px; padding: 2px 5px;
} }
&.btn-success, &.btn-success,
...@@ -159,33 +152,42 @@ ...@@ -159,33 +152,42 @@
} }
} }
.btn-group-next { .btn-clipboard {
border: none;
padding: 0 5px;
}
.input-group-btn {
.btn { .btn {
padding: 9px 0px; @include btn-gray;
font-size: 15px; @include btn-middle;
color: #7f8fa4;
border-color: #e7e9ed;
width: 140px;
.badge { &:hover {
font-weight: normal; outline: none;
background-color: #eee;
color: #78a;
} }
&.active { &:focus {
border-color: $gl-info; outline: none;
background: $gl-info; }
color: #fff;
.badge { &:active {
color: $gl-info; outline: none;
background-color: white;
} }
&.btn-clipboard {
padding-left: 15px;
padding-right: 15px;
} }
} }
}
.btn-clipboard { .active {
border: none; @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border: 1px solid #c6cacf !important;
background-color: #e4e7ed !important;
}
.btn-green {
@include btn-green
}
} }
...@@ -374,75 +374,6 @@ table { ...@@ -374,75 +374,6 @@ table {
} }
} }
.center-top-menu, .left-top-menu {
@include nav-menu;
text-align: center;
margin-top: 5px;
margin-bottom: $gl-padding;
height: auto;
margin-top: -$gl-padding;
&.no-bottom {
margin-bottom: 0;
}
&.no-top {
margin-top: 0;
}
li a {
display: inline-block;
padding-top: $gl-padding;
padding-bottom: 11px;
margin-bottom: -1px;
}
&.bottom-border {
border-bottom: 1px solid $border-color;
height: 57px;
}
&.wide {
margin-left: -$gl-padding;
margin-right: -$gl-padding;
}
}
.left-top-menu {
text-align: left;
border-bottom: 1px solid #EEE;
}
.center-middle-menu {
@include nav-menu;
padding: 0;
text-align: center;
margin: -$gl-padding;
margin-top: 0;
margin-bottom: 0;
height: 58px;
border-bottom: 1px solid $border-color;
li {
&:after {
content: "|";
color: $border-gray-light;
}
&:last-child {
&:after {
content: none;
}
}
> a {
display: inline-block;
text-transform: uppercase;
font-size: 13px;
}
}
}
.dropzone .dz-preview .dz-progress { .dropzone .dz-preview .dz-progress {
border-color: $border-color !important; border-color: $border-color !important;
} }
......
...@@ -3,11 +3,8 @@ ...@@ -3,11 +3,8 @@
* *
*/ */
.file-holder { .file-holder {
margin-left: -$gl-padding;
margin-right: -$gl-padding;
border: none; border: none;
border-top: 1px solid #E7E9EE; border: 1px solid $border-color;
border-bottom: 1px solid #E7E9EE;
&.readme-holder { &.readme-holder {
border-bottom: 0; border-bottom: 0;
......
...@@ -8,10 +8,12 @@ ...@@ -8,10 +8,12 @@
.flash-notice { .flash-notice {
@extend .alert; @extend .alert;
@extend .alert-info; @extend .alert-info;
margin: 0;
} }
.flash-alert { .flash-alert {
@extend .alert; @extend .alert;
@extend .alert-danger; @extend .alert-danger;
margin: 0;
} }
} }
...@@ -74,8 +74,6 @@ label { ...@@ -74,8 +74,6 @@ label {
.form-control { .form-control {
@include box-shadow(none); @include box-shadow(none);
height: 42px;
padding: 8px $gl-padding;
} }
.form-control-inline { .form-control-inline {
......
...@@ -28,6 +28,7 @@ header { ...@@ -28,6 +28,7 @@ header {
min-height: $header-height; min-height: $header-height;
background-color: #fff; background-color: #fff;
border: none; border: none;
border-bottom: 1px solid #EEE;
.container-fluid { .container-fluid {
width: 100% !important; width: 100% !important;
......
...@@ -5,8 +5,6 @@ html { ...@@ -5,8 +5,6 @@ html {
} }
body { body {
background-color: #F3F3F3 !important;
&.navless { &.navless {
background-color: white !important; background-color: white !important;
} }
......
...@@ -109,10 +109,8 @@ ul.content-list { ...@@ -109,10 +109,8 @@ ul.content-list {
padding: 0; padding: 0;
> li { > li {
padding: $gl-padding; padding: $gl-padding 0;
border-color: $table-border-color; border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
color: $gl-gray; color: $gl-gray;
.avatar { .avatar {
...@@ -133,6 +131,7 @@ ul.content-list { ...@@ -133,6 +131,7 @@ ul.content-list {
.panel > .content-list { .panel > .content-list {
li { li {
margin: 0; margin: 0;
padding: $gl-padding;
} }
} }
......
...@@ -65,13 +65,6 @@ ...@@ -65,13 +65,6 @@
position: relative; position: relative;
} }
.md-header {
ul {
float: left;
margin-bottom: 1px;
}
}
.referenced-users { .referenced-users {
color: #4c4e54; color: #4c4e54;
padding-top: 10px; padding-top: 10px;
...@@ -85,28 +78,12 @@ ...@@ -85,28 +78,12 @@
box-shadow: none; box-shadow: none;
} }
.new_note,
.edit_note,
.detail-page-description,
.milestone-description,
.wiki-content,
.merge-request-form {
.nav-tabs {
margin-bottom: 0;
border: none;
li a,
li.active a {
border: 1px solid #DDD;
}
}
}
.markdown-area { .markdown-area {
@include border-radius(0); @include border-radius(0);
background: #FFF; background: #FFF;
border: 1px solid #ddd; border: 1px solid #ddd;
min-height: 140px; min-height: 140px;
max-height: 430px;
padding: 5px; padding: 5px;
box-shadow: none; box-shadow: none;
width: 100%; width: 100%;
......
...@@ -118,38 +118,3 @@ ...@@ -118,38 +118,3 @@
font-size: 16px; font-size: 16px;
line-height: 24px; line-height: 24px;
} }
@mixin nav-menu {
padding: 0;
margin: 0;
list-style: none;
height: 56px;
li {
display: inline-block;
a {
padding: 14px;
font-size: 15px;
line-height: 28px;
color: #959494;
border-bottom: 2px solid transparent;
&:hover, &:active, &:focus {
text-decoration: none;
outline: none;
}
}
&.active a {
color: #616060;
border-bottom: 2px solid #4688f1;
}
.badge {
font-weight: normal;
background-color: #eee;
color: #78a;
}
}
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
padding-right: 5px; padding-right: 5px;
} }
.nav.nav-tabs > li > a { .nav-links > li > a {
padding: 10px; padding: 10px;
font-size: 12px; font-size: 12px;
margin-right: 3px; margin-right: 3px;
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
display: none; display: none;
} }
.center-top-menu, .left-top-menu { .nav-links, .nav-links {
li a { li a {
font-size: 14px; font-size: 14px;
padding: 19px 10px; padding: 19px 10px;
...@@ -100,11 +100,6 @@ ...@@ -100,11 +100,6 @@
} }
@media (max-width: $screen-sm-max) { @media (max-width: $screen-sm-max) {
.page-with-sidebar .content-wrapper {
padding: 0;
padding-top: 1px;
}
.issues-filters { .issues-filters {
.milestone-filter, .labels-filter { .milestone-filter, .labels-filter {
display: none; display: none;
......
.nav-links {
padding: 0;
margin: 0;
list-style: none;
height: auto;
border-bottom: 1px solid $border-color;
li {
display: inline-block;
a {
display: inline-block;
padding: 14px;
padding-top: $gl-padding;
padding-bottom: 11px;
margin-bottom: -1px;
font-size: 15px;
line-height: 28px;
color: #959494;
border-bottom: 2px solid transparent;
&:hover, &:active, &:focus {
text-decoration: none;
outline: none;
}
}
&.active a {
color: #000000;
border-bottom: 2px solid #4688f1;
}
.badge {
font-weight: normal;
background-color: #eee;
color: #78a;
}
}
}
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
.select2-choice { .select2-choice {
background: #FFF; background: #FFF;
border-color: #DDD; border-color: #DDD;
height: 42px; height: 36px;
padding: 8px $gl-padding; padding: 6px $gl-padding;
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: 1.42857143; line-height: 1.42857143;
......
...@@ -21,11 +21,10 @@ ...@@ -21,11 +21,10 @@
.content-wrapper { .content-wrapper {
width: 100%; width: 100%;
padding: 20px;
.container-fluid { .container-fluid {
background: #FFF; background: #FFF;
padding: $gl-padding; padding: 0 $gl-padding;
&.container-blank { &.container-blank {
background: none; background: none;
......
.table-holder { .table-holder {
margin: -$gl-padding; margin: 0;
margin-top: 0;
margin-bottom: 0;
} }
table { table {
...@@ -32,6 +30,7 @@ table { ...@@ -32,6 +30,7 @@ table {
} }
th { th {
background-color: $background-color;
font-weight: normal; font-weight: normal;
font-size: 15px; font-size: 15px;
border-bottom: 1px solid $border-color !important; border-bottom: 1px solid $border-color !important;
......
...@@ -5,10 +5,8 @@ ...@@ -5,10 +5,8 @@
padding: 0; padding: 0;
.timeline-entry { .timeline-entry {
padding: $gl-padding; padding: $gl-padding 0;
border-color: $table-border-color; border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
color: $gl-gray; color: $gl-gray;
border-bottom: 1px solid $border-white-light; border-bottom: 1px solid $border-white-light;
......
...@@ -99,47 +99,6 @@ ...@@ -99,47 +99,6 @@
} }
} }
// Nav tabs
.nav.nav-tabs {
margin-bottom: 15px;
li {
> a {
margin-right: 5px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i.fa {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
font-weight: bold;
}
}
}
}
.nav-tabs > li > a,
.nav-pills > li > a {
color: #666;
}
.nav-pills > .active > a > span > .badge {
background-color: #fff;
color: $gl-primary;
}
/** /**
* fix to keep tooltips position in top navigation bar * fix to keep tooltips position in top navigation bar
......
...@@ -46,7 +46,7 @@ $font-size-base: $gl-font-size; ...@@ -46,7 +46,7 @@ $font-size-base: $gl-font-size;
// //
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). //## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
$padding-base-vertical: 9px; $padding-base-vertical: $gl-vert-padding;
$padding-base-horizontal: $gl-padding; $padding-base-horizontal: $gl-padding;
$component-active-color: #fff; $component-active-color: #fff;
$component-active-bg: $brand-info; $component-active-bg: $brand-info;
......
...@@ -177,7 +177,7 @@ body { ...@@ -177,7 +177,7 @@ body {
} }
.page-title { .page-title {
margin-top: 0px; margin-top: $gl-padding;
line-height: 1.3; line-height: 1.3;
font-size: 1.25em; font-size: 1.25em;
font-weight: 600; font-weight: 600;
......
...@@ -22,6 +22,7 @@ $header-height: 58px; ...@@ -22,6 +22,7 @@ $header-height: 58px;
$fixed-layout-width: 1280px; $fixed-layout-width: 1280px;
$gl-gray: #5a5a5a; $gl-gray: #5a5a5a;
$gl-padding: 16px; $gl-padding: 16px;
$gl-vert-padding: 6px;
$gl-padding-top:10px; $gl-padding-top:10px;
$gl-avatar-size: 46px; $gl-avatar-size: 46px;
$secondary-text: #7f8fa4; $secondary-text: #7f8fa4;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 4px; right: 4px;
line-height: 40px; line-height: 56px;
} }
a.js-zen-leave { a.js-zen-leave {
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
} }
.commit-box { .commit-box {
border-top: 1px solid $border-color;
.commit-title { .commit-title {
margin: 0; margin: 0;
font-size: 23px; font-size: 23px;
......
.detail-page-header { .detail-page-header {
margin: -$gl-padding; padding: 11px 0;
padding: 7px $gl-padding;
margin-bottom: 0px;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
color: #5c5d5e; color: #5c5d5e;
font-size: 16px; font-size: 16px;
......
// Common // Common
.diff-file { .diff-file {
margin-left: -$gl-padding; border: 1px solid $border-color;
margin-right: -$gl-padding; border-top: none;
border: none;
border-bottom: 1px solid #E7E9EE;
.diff-header { .diff-header {
position: relative; position: relative;
...@@ -23,14 +21,6 @@ ...@@ -23,14 +21,6 @@
} }
} }
.diff-controls {
.btn {
padding: 0px 10px;
font-size: 13px;
line-height: 28px;
}
}
.commit-short-id { .commit-short-id {
font-family: $monospace_font; font-family: $monospace_font;
font-size: smaller; font-size: smaller;
......
...@@ -4,9 +4,7 @@ ...@@ -4,9 +4,7 @@
*/ */
.event-item { .event-item {
font-size: $gl-font-size; font-size: $gl-font-size;
padding: $gl-padding $gl-padding $gl-padding ($gl-padding + $gl-avatar-size + 15px); padding: $gl-padding 0 $gl-padding ($gl-avatar-size + 15px);
margin-left: -$gl-padding;
margin-right: -$gl-padding;
border-bottom: 1px solid $table-border-color; border-bottom: 1px solid $table-border-color;
color: #7f8fa4; color: #7f8fa4;
......
...@@ -27,10 +27,10 @@ ...@@ -27,10 +27,10 @@
.project-issuable-filter { .project-issuable-filter {
.controls { .controls {
float: right; float: right;
margin-top: 7px; margin-top: 11px;
} }
.center-top-menu { .nav-links {
text-align: left; text-align: left;
} }
} }
...@@ -105,8 +105,13 @@ ...@@ -105,8 +105,13 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
cite {
font-style: normal;
}
button { button {
float: right; float: right;
padding: 3px 5px;
} }
} }
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
* *
*/ */
.mr-state-widget { .mr-state-widget {
background: #F7F8FA; background: $background-color;
color: $gl-gray; color: $gl-gray;
border: 1px solid #dce0e6; border: 1px solid $border-color;
@include border-radius(2px); @include border-radius(2px);
form { form {
......
...@@ -159,6 +159,7 @@ ...@@ -159,6 +159,7 @@
.edit_note { .edit_note {
.markdown-area { .markdown-area {
min-height: 140px; min-height: 140px;
max-height: 430px;
} }
.note-form-actions { .note-form-actions {
background: transparent; background: transparent;
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
} }
.project-home-panel { .project-home-panel {
padding-bottom: 40px;
border-bottom: 1px solid $border-color;
.cover-controls { .cover-controls {
.project-settings-dropdown { .project-settings-dropdown {
...@@ -51,6 +53,8 @@ ...@@ -51,6 +53,8 @@
} }
.notifications-btn { .notifications-btn {
margin-top: -28px;
.fa-bell { .fa-bell {
margin-right: 6px; margin-right: 6px;
} }
...@@ -75,17 +79,6 @@ ...@@ -75,17 +79,6 @@
} }
} }
.git-clone-holder {
max-width: 498px;
.form-control {
background: #FFF;
font-size: 14px;
height: 42px;
margin-left: -1px;
}
}
.visibility-level-label { .visibility-level-label {
@extend .btn; @extend .btn;
@extend .btn-gray; @extend .btn-gray;
...@@ -98,11 +91,6 @@ ...@@ -98,11 +91,6 @@
} }
} }
.git-clone-holder {
display: inline-table;
position: relative;
}
.project-repo-buttons { .project-repo-buttons {
margin-top: 12px; margin-top: 12px;
margin-bottom: 0px; margin-bottom: 0px;
...@@ -112,10 +100,22 @@ ...@@ -112,10 +100,22 @@
margin-bottom: 12px; margin-bottom: 12px;
} }
.clone-row {
.split-repo-buttons,
.project-clone-holder {
display: inline-block;
}
.split-repo-buttons {
margin: 0 12px;
}
}
.btn { .btn {
@include btn-gray; @include btn-gray;
text-transform: none; text-transform: none;
} }
.count-with-arrow { .count-with-arrow {
display: inline-block; display: inline-block;
position: relative; position: relative;
...@@ -160,8 +160,8 @@ ...@@ -160,8 +160,8 @@
border-style: solid; border-style: solid;
font-size: 13px; font-size: 13px;
font-weight: 600; font-weight: 600;
line-height: 20px; line-height: 13px;
padding: 11px 16px; padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px; letter-spacing: .4px;
padding: 10px; padding: 10px;
text-align: center; text-align: center;
...@@ -189,117 +189,6 @@ ...@@ -189,117 +189,6 @@
} }
} }
.git-clone-holder {
.project-home-dropdown + & {
margin-right: 45px;
}
.clone-options {
display: table-cell;
a.btn {
width: 100%;
}
}
.form-control {
cursor: auto;
@extend .monospace;
background: #FAFAFA;
width: 101%;
}
.input-group-addon {
background: #f7f8fa;
&.git-protocols {
padding: 0;
border: none;
.input-group-btn:last-child > .btn {
@include border-radius-right(0);
border-left: 1px solid #c6cacf;
margin-left: -2px !important;
}
}
}
}
.projects-search-form {
.input-group .form-control {
height: 42px;
}
}
.input-group-btn {
.btn {
@include btn-gray;
@include btn-middle;
&:hover {
outline: none;
}
&:focus {
outline: none;
}
&:active {
outline: none;
}
&.btn-clipboard {
padding-left: 15px;
padding-right: 15px;
}
}
.active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border: 1px solid #c6cacf !important;
background-color: #e4e7ed !important;
}
.btn-green {
@include btn-green
}
}
.split-repo-buttons {
display: inline-table;
margin: 0 12px 0 12px;
.btn{
@include btn-gray;
@include btn-default;
}
.dropdown-toggle {
margin: -5px;
}
}
#notification-form {
margin-left: 5px;
}
.dropdown-new {
margin-left: -5px;
}
.open > .dropdown-new.btn {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border: 1px solid #c6cacf !important;
background-color: #e4e7ed !important;
text-transform: none;
color: #313236 !important;
font-size: 15px;
}
.dropdown-menu { .dropdown-menu {
@include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px); @include box-shadow(rgba(76, 86, 103, 0.247059) 0px 0px 1px 0px, rgba(31, 37, 50, 0.317647) 0px 2px 18px 0px);
@include border-radius (0px); @include border-radius (0px);
...@@ -351,28 +240,6 @@ ...@@ -351,28 +240,6 @@
color: #555; color: #555;
} }
ul.nav.nav-projects-tabs {
@extend .nav-tabs;
padding-left: 8px;
li {
a {
padding: 6px 25px;
margin-top: 2px;
border-color: #DDD;
background-color: #EEE;
text-shadow: 0 1px 1px white;
color: #555;
}
&.active {
a {
font-weight: bold;
}
}
}
}
.project_member_row form { .project_member_row form {
margin: 0px; margin: 0px;
} }
...@@ -399,9 +266,9 @@ ul.nav.nav-projects-tabs { ...@@ -399,9 +266,9 @@ ul.nav.nav-projects-tabs {
.breadcrumb.repo-breadcrumb { .breadcrumb.repo-breadcrumb {
padding: 0; padding: 0;
line-height: 42px;
background: transparent; background: transparent;
border: none; border: none;
line-height: 42px;
margin: 0; margin: 0;
> li + li:before { > li + li:before {
...@@ -416,11 +283,8 @@ ul.nav.nav-projects-tabs { ...@@ -416,11 +283,8 @@ ul.nav.nav-projects-tabs {
.top-area { .top-area {
border-bottom: 1px solid #EEE; border-bottom: 1px solid #EEE;
margin: 0 -16px;
padding: 0 $gl-padding;
height: 42px;
ul.left-top-menu { ul.nav-links {
display: inline-block; display: inline-block;
width: 50%; width: 50%;
margin-bottom: 0px; margin-bottom: 0px;
...@@ -431,12 +295,12 @@ ul.nav.nav-projects-tabs { ...@@ -431,12 +295,12 @@ ul.nav.nav-projects-tabs {
width: 50%; width: 50%;
display: inline-block; display: inline-block;
float: right; float: right;
padding-top: 7px; padding-top: 11px;
text-align: right; text-align: right;
.btn-green { .btn-green {
margin-top: -2px;
margin-left: 10px; margin-left: 10px;
float: right;
} }
} }
...@@ -482,11 +346,11 @@ table.table.protected-branches-list tr.no-border { ...@@ -482,11 +346,11 @@ table.table.protected-branches-list tr.no-border {
padding-top: 10px; padding-top: 10px;
padding-bottom: 4px; padding-bottom: 4px;
ul.nav-pills { ul.nav {
display:inline-block; display:inline-block;
} }
.nav-pills li { .nav li {
display:inline; display:inline;
} }
...@@ -523,8 +387,7 @@ pre.light-well { ...@@ -523,8 +387,7 @@ pre.light-well {
} }
.projects-search-form { .projects-search-form {
margin: -$gl-padding; padding: $gl-padding 0;
padding: $gl-padding;
padding-bottom: 0; padding-bottom: 0;
margin-bottom: 0px; margin-bottom: 0px;
...@@ -574,10 +437,8 @@ pre.light-well { ...@@ -574,10 +437,8 @@ pre.light-well {
@include basic-list; @include basic-list;
.project-row { .project-row {
padding: $gl-padding; padding: $gl-padding 0;
border-color: $table-border-color; border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
&.no-description { &.no-description {
.project { .project {
...@@ -631,8 +492,6 @@ pre.light-well { ...@@ -631,8 +492,6 @@ pre.light-well {
} }
.project-last-commit { .project-last-commit {
margin: 0 7px;
.ci-status { .ci-status {
margin-right: 16px; margin-right: 16px;
} }
...@@ -662,9 +521,7 @@ pre.light-well { ...@@ -662,9 +521,7 @@ pre.light-well {
} }
.project-show-readme .readme-holder { .project-show-readme .readme-holder {
margin-left: -$gl-padding; padding: $gl-padding 0;
margin-right: -$gl-padding;
padding: ($gl-padding + 7px);
border-top: 0; border-top: 0;
.edit-project-readme { .edit-project-readme {
...@@ -672,3 +529,32 @@ pre.light-well { ...@@ -672,3 +529,32 @@ pre.light-well {
position: relative; position: relative;
} }
} }
.git-clone-holder {
width: 498px;
.btn-clipboard {
border: 1px solid $border-color;
padding: 6px $gl-padding;
}
.project-home-dropdown + & {
margin-right: 45px;
}
.clone-options {
display: table-cell;
a.btn {
width: 100%;
}
}
.form-control {
@extend .monospace;
background: #FFF;
font-size: 14px;
margin-left: -1px;
cursor: auto;
width: 101%;
}
}
.tree-holder { .tree-holder {
> .nav-block {
margin: 11px 0;
}
.file-finder { .file-finder {
width: 50%; width: 50%;
...@@ -13,7 +16,7 @@ ...@@ -13,7 +16,7 @@
tr { tr {
> td, > th { > td, > th {
line-height: 28px; line-height: 26px;
} }
&:hover { &:hover {
...@@ -86,12 +89,14 @@ ...@@ -86,12 +89,14 @@
.blob-commit-info { .blob-commit-info {
list-style: none; list-style: none;
padding: $gl-padding;
background: $background-color;
border: 1px solid $border-color;
border-bottom: none;
margin: 0; margin: 0;
padding: 0;
margin-bottom: 5px;
.commit { .commit {
padding: $gl-padding 0; padding: 0;
.commit-row-title { .commit-row-title {
.commit-row-message { .commit-row-message {
...@@ -115,3 +120,8 @@ ...@@ -115,3 +120,8 @@
font-weight: normal; font-weight: normal;
color: $md-link-color; color: $md-link-color;
} }
.tree-controls {
float: right;
margin-top: 11px;
}
class Projects::ArtifactsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_build_artifacts!
def download
unless artifacts_file.file_storage?
return redirect_to artifacts_file.url
end
unless artifacts_file.exists?
return not_found!
end
send_file artifacts_file.path, disposition: 'attachment'
end
def browse
return render_404 unless build.artifacts?
directory = params[:path] ? "#{params[:path]}/" : ''
@entry = build.artifacts_metadata_entry(directory)
return render_404 unless @entry.exists?
end
def file
entry = build.artifacts_metadata_entry(params[:path])
if entry.exists?
render json: { archive: build.artifacts_file.path,
entry: Base64.encode64(entry.path) }
else
render json: {}, status: 404
end
end
private
def build
@build ||= project.builds.unscoped.find_by!(id: params[:build_id])
end
def artifacts_file
@artifacts_file ||= build.artifacts_file
end
def authorize_read_build_artifacts!
unless can?(current_user, :read_build_artifacts, @project)
if current_user.nil?
return authenticate_user!
else
return render_404
end
end
end
end
...@@ -2,7 +2,6 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -2,7 +2,6 @@ class Projects::BuildsController < Projects::ApplicationController
before_action :build, except: [:index, :cancel_all] before_action :build, except: [:index, :cancel_all]
before_action :authorize_manage_builds!, except: [:index, :show, :status] before_action :authorize_manage_builds!, except: [:index, :show, :status]
before_action :authorize_download_build_artifacts!, only: [:download]
layout "project" layout "project"
...@@ -51,18 +50,6 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -51,18 +50,6 @@ class Projects::BuildsController < Projects::ApplicationController
redirect_to build_path(build) redirect_to build_path(build)
end end
def download
unless artifacts_file.file_storage?
return redirect_to artifacts_file.url
end
unless artifacts_file.exists?
return not_found!
end
send_file artifacts_file.path, disposition: 'attachment'
end
def status def status
render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha) render json: @build.to_json(only: [:status, :id, :sha, :coverage], methods: :sha)
end end
...@@ -79,10 +66,6 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -79,10 +66,6 @@ class Projects::BuildsController < Projects::ApplicationController
@build ||= project.builds.unscoped.find_by!(id: params[:id]) @build ||= project.builds.unscoped.find_by!(id: params[:id])
end end
def artifacts_file
build.artifacts_file
end
def build_path(build) def build_path(build)
namespace_project_build_path(build.project.namespace, build.project, build) namespace_project_build_path(build.project.namespace, build.project, build)
end end
...@@ -92,14 +75,4 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -92,14 +75,4 @@ class Projects::BuildsController < Projects::ApplicationController
return page_404 return page_404
end end
end end
def authorize_download_build_artifacts!
unless can?(current_user, :download_build_artifacts, @project)
if current_user.nil?
return authenticate_user!
else
return render_404
end
end
end
end end
class SentNotificationsController < ApplicationController
skip_before_action :authenticate_user!
def unsubscribe
@sent_notification = SentNotification.for(params[:id])
return render_404 unless @sent_notification && @sent_notification.unsubscribable?
noteable = @sent_notification.noteable
noteable.unsubscribe(@sent_notification.recipient)
flash[:notice] = "You have been unsubscribed from this thread."
if current_user
case noteable
when Issue
redirect_to issue_path(noteable)
when MergeRequest
redirect_to merge_request_path(noteable)
else
redirect_to root_path
end
else
redirect_to new_user_session_path
end
end
end
...@@ -17,7 +17,7 @@ module ButtonHelper ...@@ -17,7 +17,7 @@ module ButtonHelper
def clipboard_button(data = {}) def clipboard_button(data = {})
content_tag :button, content_tag :button,
icon('clipboard'), icon('clipboard'),
class: 'btn btn-xs btn-clipboard', class: 'btn btn-clipboard',
data: data, data: data,
type: :button type: :button
end end
......
...@@ -27,15 +27,17 @@ module EventsHelper ...@@ -27,15 +27,17 @@ module EventsHelper
key = key.to_s key = key.to_s
active = 'active' if @event_filter.active?(key) active = 'active' if @event_filter.active?(key)
link_opts = { link_opts = {
class: "event-filter-link btn btn-default #{active}", class: "event-filter-link",
id: "#{key}_event_filter", id: "#{key}_event_filter",
title: "Filter by #{tooltip.downcase}", title: "Filter by #{tooltip.downcase}",
} }
content_tag :li, class: active do
link_to request.path, link_opts do link_to request.path, link_opts do
content_tag(:span, ' ' + tooltip) content_tag(:span, ' ' + tooltip)
end end
end end
end
def icon_for_event def icon_for_event
{ {
......
...@@ -91,7 +91,7 @@ module GitlabMarkdownHelper ...@@ -91,7 +91,7 @@ module GitlabMarkdownHelper
def render_wiki_content(wiki_page) def render_wiki_content(wiki_page)
case wiki_page.format case wiki_page.format
when :markdown when :markdown
markdown(wiki_page.content) markdown(wiki_page.content, pipeline: :wiki, project_wiki: @project_wiki)
when :asciidoc when :asciidoc
asciidoc(wiki_page.content) asciidoc(wiki_page.content)
else else
......
module Emails module Emails
module Issues module Issues
def new_issue_email(recipient_id, issue_id) def new_issue_email(recipient_id, issue_id)
issue_mail_with_notification(issue_id, recipient_id) do setup_issue_mail(issue_id, recipient_id)
mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id)) mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id))
end end
end
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id) def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id)
issue_mail_with_notification(issue_id, recipient_id) do setup_issue_mail(issue_id, recipient_id)
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
end end
end
def closed_issue_email(recipient_id, issue_id, updated_by_user_id) def closed_issue_email(recipient_id, issue_id, updated_by_user_id)
issue_mail_with_notification(issue_id, recipient_id) do setup_issue_mail(issue_id, recipient_id)
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
end end
end
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id) def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
issue_mail_with_notification(issue_id, recipient_id) do setup_issue_mail(issue_id, recipient_id)
@issue_status = status @issue_status = status
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id)) mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id))
end end
end
private private
...@@ -38,14 +38,12 @@ module Emails ...@@ -38,14 +38,12 @@ module Emails
} }
end end
def issue_mail_with_notification(issue_id, recipient_id) def setup_issue_mail(issue_id, recipient_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@project = @issue.project @project = @issue.project
@target_url = namespace_project_issue_url(@project.namespace, @project, @issue) @target_url = namespace_project_issue_url(@project.namespace, @project, @issue)
yield @sent_notification = SentNotification.record(@issue, recipient_id, reply_key)
SentNotification.record(@issue, recipient_id, reply_key)
end end
end end
end end
module Emails module Emails
module MergeRequests module MergeRequests
def new_merge_request_email(recipient_id, merge_request_id) def new_merge_request_email(recipient_id, merge_request_id)
@merge_request = MergeRequest.find(merge_request_id) setup_merge_request_mail(merge_request_id, recipient_id)
@project = @merge_request.project
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
mail_new_thread(@merge_request, mail_new_thread(@merge_request,
from: sender(@merge_request.author_id), from: sender(@merge_request.author_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
SentNotification.record(@merge_request, recipient_id, reply_key)
end end
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id) def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id) setup_merge_request_mail(merge_request_id, recipient_id)
@previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @merge_request.project
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
mail_answer_thread(@merge_request, mail_answer_thread(@merge_request,
from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
SentNotification.record(@merge_request, recipient_id, reply_key)
end end
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id) setup_merge_request_mail(merge_request_id, recipient_id)
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@project = @merge_request.project
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
mail_answer_thread(@merge_request, mail_answer_thread(@merge_request,
from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
SentNotification.record(@merge_request, recipient_id, reply_key)
end end
def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id) def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id) setup_merge_request_mail(merge_request_id, recipient_id)
@project = @merge_request.project
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
mail_answer_thread(@merge_request, mail_answer_thread(@merge_request,
from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
SentNotification.record(@merge_request, recipient_id, reply_key)
end end
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id) def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id)
@merge_request = MergeRequest.find(merge_request_id) setup_merge_request_mail(merge_request_id, recipient_id)
@mr_status = status @mr_status = status
@project = @merge_request.project
@updated_by = User.find updated_by_user_id @updated_by = User.find updated_by_user_id
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
mail_answer_thread(@merge_request, mail_answer_thread(@merge_request,
from: sender(updated_by_user_id), from: sender(updated_by_user_id),
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@merge_request.title} (##{@merge_request.iid})")) subject: subject("#{@merge_request.title} (##{@merge_request.iid})"))
end
private
def setup_merge_request_mail(merge_request_id, recipient_id)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = namespace_project_merge_request_url(@project.namespace,
@project,
@merge_request)
SentNotification.record(@merge_request, recipient_id, reply_key) @sent_notification = SentNotification.record(@merge_request, recipient_id, reply_key)
end end
end end
end end
module Emails module Emails
module Notes module Notes
def note_commit_email(recipient_id, note_id) def note_commit_email(recipient_id, note_id)
note_mail_with_notification(note_id, recipient_id) do setup_note_mail(note_id, recipient_id)
@commit = @note.noteable @commit = @note.noteable
@target_url = namespace_project_commit_url(*note_target_url_options) @target_url = namespace_project_commit_url(*note_target_url_options)
...@@ -10,23 +11,22 @@ module Emails ...@@ -10,23 +11,22 @@ module Emails
to: recipient(recipient_id), to: recipient(recipient_id),
subject: subject("#{@commit.title} (#{@commit.short_id})")) subject: subject("#{@commit.title} (#{@commit.short_id})"))
end end
end
def note_issue_email(recipient_id, note_id) def note_issue_email(recipient_id, note_id)
note_mail_with_notification(note_id, recipient_id) do setup_note_mail(note_id, recipient_id)
@issue = @note.noteable @issue = @note.noteable
@target_url = namespace_project_issue_url(*note_target_url_options) @target_url = namespace_project_issue_url(*note_target_url_options)
mail_answer_thread(@issue, note_thread_options(recipient_id)) mail_answer_thread(@issue, note_thread_options(recipient_id))
end end
end
def note_merge_request_email(recipient_id, note_id) def note_merge_request_email(recipient_id, note_id)
note_mail_with_notification(note_id, recipient_id) do setup_note_mail(note_id, recipient_id)
@merge_request = @note.noteable @merge_request = @note.noteable
@target_url = namespace_project_merge_request_url(*note_target_url_options) @target_url = namespace_project_merge_request_url(*note_target_url_options)
mail_answer_thread(@merge_request, note_thread_options(recipient_id)) mail_answer_thread(@merge_request, note_thread_options(recipient_id))
end end
end
private private
...@@ -42,13 +42,11 @@ module Emails ...@@ -42,13 +42,11 @@ module Emails
} }
end end
def note_mail_with_notification(note_id, recipient_id) def setup_note_mail(note_id, recipient_id)
@note = Note.find(note_id) @note = Note.find(note_id)
@project = @note.project @project = @note.project
yield @sent_notification = SentNotification.record_note(@note, recipient_id, reply_key)
SentNotification.record_note(@note, recipient_id, reply_key)
end end
end end
end end
...@@ -107,10 +107,9 @@ class Notify < BaseMailer ...@@ -107,10 +107,9 @@ class Notify < BaseMailer
end end
headers["X-GitLab-#{model.class.name}-ID"] = model.id headers["X-GitLab-#{model.class.name}-ID"] = model.id
if reply_key
headers['X-GitLab-Reply-Key'] = reply_key headers['X-GitLab-Reply-Key'] = reply_key
if Gitlab::IncomingEmail.enabled?
address = Mail::Address.new(Gitlab::IncomingEmail.reply_address(reply_key)) address = Mail::Address.new(Gitlab::IncomingEmail.reply_address(reply_key))
address.display_name = @project.name_with_namespace address.display_name = @project.name_with_namespace
......
...@@ -175,7 +175,7 @@ class Ability ...@@ -175,7 +175,7 @@ class Ability
:create_merge_request, :create_merge_request,
:create_wiki, :create_wiki,
:manage_builds, :manage_builds,
:download_build_artifacts, :read_build_artifacts,
:push_code :push_code
] ]
end end
......
...@@ -30,10 +30,12 @@ ...@@ -30,10 +30,12 @@
# description :string(255) # description :string(255)
# artifacts_file :text # artifacts_file :text
# gl_project_id :integer # gl_project_id :integer
# artifacts_metadata :text
# #
module Ci module Ci
class Build < CommitStatus class Build < CommitStatus
include Gitlab::Application.routes.url_helpers
LAZY_ATTRIBUTES = ['trace'] LAZY_ATTRIBUTES = ['trace']
belongs_to :runner, class_name: 'Ci::Runner' belongs_to :runner, class_name: 'Ci::Runner'
...@@ -49,6 +51,7 @@ module Ci ...@@ -49,6 +51,7 @@ module Ci
scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) } scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader
acts_as_taggable acts_as_taggable
...@@ -291,20 +294,17 @@ module Ci ...@@ -291,20 +294,17 @@ module Ci
end end
def target_url def target_url
Gitlab::Application.routes.url_helpers.
namespace_project_build_url(project.namespace, project, self) namespace_project_build_url(project.namespace, project, self)
end end
def cancel_url def cancel_url
if active? if active?
Gitlab::Application.routes.url_helpers.
cancel_namespace_project_build_path(project.namespace, project, self) cancel_namespace_project_build_path(project.namespace, project, self)
end end
end end
def retry_url def retry_url
if retryable? if retryable?
Gitlab::Application.routes.url_helpers.
retry_namespace_project_build_path(project.namespace, project, self) retry_namespace_project_build_path(project.namespace, project, self)
end end
end end
...@@ -321,20 +321,35 @@ module Ci ...@@ -321,20 +321,35 @@ module Ci
pending? && !any_runners_online? pending? && !any_runners_online?
end end
def download_url
if artifacts_file.exists?
Gitlab::Application.routes.url_helpers.
download_namespace_project_build_path(project.namespace, project, self)
end
end
def execute_hooks def execute_hooks
build_data = Gitlab::BuildDataBuilder.build(self) build_data = Gitlab::BuildDataBuilder.build(self)
project.execute_hooks(build_data.dup, :build_hooks) project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks) project.execute_services(build_data.dup, :build_hooks)
end end
def artifacts?
artifacts_file.exists?
end
def artifacts_download_url
if artifacts?
download_namespace_project_build_artifacts_path(project.namespace, project, self)
end
end
def artifacts_browse_url
if artifacts_browser_supported?
browse_namespace_project_build_artifacts_path(project.namespace, project, self)
end
end
def artifacts_browser_supported?
artifacts? && artifacts_metadata.exists?
end
def artifacts_metadata_entry(path)
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path).to_entry
end
private private
......
...@@ -56,6 +56,8 @@ class CommitStatus < ActiveRecord::Base ...@@ -56,6 +56,8 @@ class CommitStatus < ActiveRecord::Base
scope :ordered, -> { order(:ref, :stage_idx, :name) } scope :ordered, -> { order(:ref, :stage_idx, :name) }
scope :for_ref, ->(ref) { where(ref: ref) } scope :for_ref, ->(ref) { where(ref: ref) }
AVAILABLE_STATUSES = ['pending', 'running', 'success', 'failed', 'canceled']
state_machine :status, initial: :pending do state_machine :status, initial: :pending do
event :run do event :run do
transition pending: :running transition pending: :running
...@@ -131,7 +133,11 @@ class CommitStatus < ActiveRecord::Base ...@@ -131,7 +133,11 @@ class CommitStatus < ActiveRecord::Base
false false
end end
def download_url def artifacts_download_url
nil
end
def artifacts_browse_url
nil nil
end end
end end
...@@ -119,6 +119,12 @@ module Issuable ...@@ -119,6 +119,12 @@ module Issuable
update(subscribed: !subscribed?(user)) update(subscribed: !subscribed?(user))
end end
def unsubscribe(user)
subscriptions.
find_or_initialize_by(user_id: user.id).
update(subscribed: false)
end
def to_hook_data(user) def to_hook_data(user)
{ {
object_kind: self.class.name.underscore, object_kind: self.class.name.underscore,
......
...@@ -38,6 +38,10 @@ class ProjectWiki ...@@ -38,6 +38,10 @@ class ProjectWiki
[Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('') [Gitlab.config.gitlab.url, "/", path_with_namespace, ".git"].join('')
end end
def wiki_base_path
["/", @project.path_with_namespace, "/wikis"].join('')
end
# Returns the Gollum::Wiki object. # Returns the Gollum::Wiki object.
def wiki def wiki
@wiki ||= begin @wiki ||= begin
......
...@@ -25,8 +25,6 @@ class SentNotification < ActiveRecord::Base ...@@ -25,8 +25,6 @@ class SentNotification < ActiveRecord::Base
class << self class << self
def reply_key def reply_key
return nil unless Gitlab::IncomingEmail.enabled?
SecureRandom.hex(16) SecureRandom.hex(16)
end end
...@@ -64,6 +62,10 @@ class SentNotification < ActiveRecord::Base ...@@ -64,6 +62,10 @@ class SentNotification < ActiveRecord::Base
end end
end end
def unsubscribable?
!for_commit?
end
def for_commit? def for_commit?
noteable_type == "Commit" noteable_type == "Commit"
end end
...@@ -75,4 +77,8 @@ class SentNotification < ActiveRecord::Base ...@@ -75,4 +77,8 @@ class SentNotification < ActiveRecord::Base
super super
end end
end end
def to_param
self.reply_key
end
end end
...@@ -169,7 +169,7 @@ class WikiPage ...@@ -169,7 +169,7 @@ class WikiPage
private private
def set_attributes def set_attributes
attributes[:slug] = @page.escaped_url_path attributes[:slug] = @page.url_path
attributes[:title] = @page.title attributes[:title] = @page.title
attributes[:format] = @page.format attributes[:format] = @page.format
end end
......
...@@ -44,7 +44,7 @@ module MergeRequests ...@@ -44,7 +44,7 @@ module MergeRequests
def after_merge def after_merge
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request) MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
if params[:should_remove_source_branch] if params[:should_remove_source_branch].present?
DeleteBranchService.new(@merge_request.source_project, current_user). DeleteBranchService.new(@merge_request.source_project, current_user).
execute(merge_request.source_branch) execute(merge_request.source_branch)
end end
......
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :download_build_artifacts, project) && build.download_url - if current_user && can?(current_user, :read_build_artifacts, project) && build.artifacts?
= link_to build.download_url, title: 'Download artifacts' do = link_to build.artifacts_download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, build.project) - if current_user && can?(current_user, :manage_builds, build.project)
- if build.active? - if build.active?
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
- if @all_builds.running_or_pending.any? - if @all_builds.running_or_pending.any?
= link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
%ul.center-top-menu %ul.nav-links
%li{class: ('active' if @scope.nil?)} %li{class: ('active' if @scope.nil?)}
= link_to admin_builds_path do = link_to admin_builds_path do
All All
......
- page_title "Logs" - page_title "Logs"
- loggers = [Gitlab::GitLogger, Gitlab::AppLogger, - loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
Gitlab::ProductionLogger, Gitlab::SidekiqLogger] Gitlab::ProductionLogger, Gitlab::SidekiqLogger]
%ul.nav.nav-tabs.log-tabs %ul.nav-links.log-tabs
- loggers.each do |klass| - loggers.each do |klass|
%li{ class: (klass == Gitlab::GitLogger ? 'active' : '') } %li{ class: (klass == Gitlab::GitLogger ? 'active' : '') }
= link_to klass::file_name, "##{klass::file_name_noext}", = link_to klass::file_name, "##{klass::file_name_noext}",
'data-toggle' => 'tab' 'data-toggle' => 'tab'
%p.light To prevent performance issues admin logs output the last 2000 lines .gray-content-block
To prevent performance issues admin logs output the last 2000 lines
.tab-content .tab-content
- loggers.each do |klass| - loggers.each do |klass|
.tab-pane{ class: (klass == Gitlab::GitLogger ? 'active' : ''), .tab-pane{ class: (klass == Gitlab::GitLogger ? 'active' : ''),
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Edit Edit
%hr %hr
%ul.nav.nav-tabs %ul.nav-links
= nav_link(path: 'users#show') do = nav_link(path: 'users#show') do
= link_to "Account", admin_user_path(@user) = link_to "Account", admin_user_path(@user)
= nav_link(path: 'users#groups') do = nav_link(path: 'users#groups') do
...@@ -23,3 +23,4 @@ ...@@ -23,3 +23,4 @@
= link_to "SSH keys", keys_admin_user_path(@user) = link_to "SSH keys", keys_admin_user_path(@user)
= nav_link(controller: :identities) do = nav_link(controller: :identities) do
= link_to "Identities", admin_user_identities_path(@user) = link_to "Identities", admin_user_identities_path(@user)
.append-bottom-default
- page_title "Users" - page_title "Users"
= render 'shared/show_aside' = render 'shared/show_aside'
.row .admin-filter
%aside.col-md-3 %ul.nav-links
.admin-filter
%ul.nav.nav-pills.nav-stacked
%li{class: "#{'active' unless params[:filter]}"} %li{class: "#{'active' unless params[:filter]}"}
= link_to admin_users_path do = link_to admin_users_path do
Active Active
%small.pull-right= number_with_delimiter(User.active.count) %small.badge= number_with_delimiter(User.active.count)
%li{class: "#{'active' if params[:filter] == "admins"}"} %li{class: "#{'active' if params[:filter] == "admins"}"}
= link_to admin_users_path(filter: "admins") do = link_to admin_users_path(filter: "admins") do
Admins Admins
%small.pull-right= number_with_delimiter(User.admins.count) %small.badge= number_with_delimiter(User.admins.count)
%li.filter-two-factor-enabled{class: "#{'active' if params[:filter] == 'two_factor_enabled'}"} %li.filter-two-factor-enabled{class: "#{'active' if params[:filter] == 'two_factor_enabled'}"}
= link_to admin_users_path(filter: 'two_factor_enabled') do = link_to admin_users_path(filter: 'two_factor_enabled') do
2FA Enabled 2FA Enabled
%small.pull-right= number_with_delimiter(User.with_two_factor.count) %small.badge= number_with_delimiter(User.with_two_factor.count)
%li.filter-two-factor-disabled{class: "#{'active' if params[:filter] == 'two_factor_disabled'}"} %li.filter-two-factor-disabled{class: "#{'active' if params[:filter] == 'two_factor_disabled'}"}
= link_to admin_users_path(filter: 'two_factor_disabled') do = link_to admin_users_path(filter: 'two_factor_disabled') do
2FA Disabled 2FA Disabled
%small.pull-right= number_with_delimiter(User.without_two_factor.count) %small.badge= number_with_delimiter(User.without_two_factor.count)
%li{class: "#{'active' if params[:filter] == "blocked"}"} %li{class: "#{'active' if params[:filter] == "blocked"}"}
= link_to admin_users_path(filter: "blocked") do = link_to admin_users_path(filter: "blocked") do
Blocked Blocked
%small.pull-right= number_with_delimiter(User.blocked.count) %small.badge= number_with_delimiter(User.blocked.count)
%li{class: "#{'active' if params[:filter] == "wop"}"} %li{class: "#{'active' if params[:filter] == "wop"}"}
= link_to admin_users_path(filter: "wop") do = link_to admin_users_path(filter: "wop") do
Without projects Without projects
%small.pull-right= number_with_delimiter(User.without_projects.count) %small.badge= number_with_delimiter(User.without_projects.count)
%hr
= form_tag admin_users_path, method: :get, class: 'form-inline' do
.form-group
= search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control', spellcheck: false
= hidden_field_tag "filter", params[:filter]
= button_tag class: 'btn btn-primary' do
%i.fa.fa-search
%hr
= link_to 'Reset', admin_users_path, class: "btn btn-cancel"
%section.col-md-9 .gray-content-block.second-block
.panel.panel-default .pull-right
.panel-heading
Users (#{number_with_delimiter(@users.total_count)})
.panel-head-actions
.dropdown.inline .dropdown.inline
%a.dropdown-toggle.btn.btn-sm{href: '#', "data-toggle" => "dropdown"} %a.dropdown-toggle.btn{href: '#', "data-toggle" => "dropdown"}
%span.light sort: %span.light sort:
- if @sort.present? - if @sort.present?
= sort_options_hash[@sort] = sort_options_hash[@sort]
...@@ -69,7 +55,16 @@ ...@@ -69,7 +55,16 @@
= link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do
= sort_title_oldest_updated = sort_title_oldest_updated
= link_to 'New User', new_admin_user_path, class: "btn btn-new btn-sm" = link_to 'New User', new_admin_user_path, class: "btn btn-new"
= form_tag admin_users_path, method: :get, class: 'form-inline' do
.form-group
= search_field_tag :name, params[:name], placeholder: 'Name, email or username', class: 'form-control', spellcheck: false
= hidden_field_tag "filter", params[:filter]
= button_tag class: 'btn btn-primary' do
%i.fa.fa-search
.panel.panel-default
%ul.well-list %ul.well-list
- @users.each do |user| - @users.each do |user|
%li %li
...@@ -103,4 +98,4 @@ ...@@ -103,4 +98,4 @@
= link_to 'Unlock', unlock_admin_user_path(user), method: :put, class: 'btn-grouped btn btn-xs btn-success', data: { confirm: 'Are you sure?' } = link_to 'Unlock', unlock_admin_user_path(user), method: :put, class: 'btn-grouped btn btn-xs btn-success', data: { confirm: 'Are you sure?' }
- if user.can_be_removed? - if user.can_be_removed?
= link_to 'Destroy', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and groups linked to this user will also be removed! Maybe block the user instead? Are you sure?" }, method: :delete, class: 'btn-grouped btn btn-xs btn-remove' = link_to 'Destroy', [:admin, user], data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and groups linked to this user will also be removed! Maybe block the user instead? Are you sure?" }, method: :delete, class: 'btn-grouped btn btn-xs btn-remove'
= paginate @users, theme: "gitlab" = paginate @users, theme: "gitlab"
.hidden-xs .hidden-xs
= render "events/event_last_push", event: @last_push = render "events/event_last_push", event: @last_push
.gray-content-block .nav-block
- if current_user - if current_user
.pull-right .controls
= link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do = link_to dashboard_projects_path(:atom, { private_token: current_user.private_token }), class: 'btn rss-btn' do
%i.fa.fa-rss %i.fa.fa-rss
= render 'shared/event_filter' = render 'shared/event_filter'
......
%ul.center-top-menu %ul.nav-links
%li{ class: ("active" unless params[:filter]) } %li{ class: ("active" unless params[:filter]) }
= link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do = link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do
Your Projects Your Projects
......
%ul.center-top-menu %ul.nav-links
= nav_link(page: dashboard_groups_path) do = nav_link(page: dashboard_groups_path) do
= link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do = link_to dashboard_groups_path, title: 'Your groups', data: {placement: 'right'} do
Your Groups Your Groups
......
= content_for :flash_message do = content_for :flash_message do
= render 'shared/project_limit' = render 'shared/project_limit'
.top-area .top-area
%ul.left-top-menu %ul.nav-links
= nav_link(page: [dashboard_projects_path, root_path]) do = nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do = link_to dashboard_projects_path, title: 'Home', class: 'shortcuts-activity', data: {placement: 'right'} do
Your Projects Your Projects
......
%ul.center-top-menu %ul.nav-links
= nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do = nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
= link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do = link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do
Your Snippets Your Snippets
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#{@milestone.open_items_count} open #{@milestone.open_items_count} open
= milestone_progress_bar(@milestone) = milestone_progress_bar(@milestone)
%ul.center-top-menu.no-top.no-bottom %ul.nav-links.no-top.no-bottom
%li.active %li.active
= link_to '#tab-issues', 'data-toggle' => 'tab' do = link_to '#tab-issues', 'data-toggle' => 'tab' do
Issues Issues
......
...@@ -3,29 +3,33 @@ ...@@ -3,29 +3,33 @@
= render 'dashboard/snippets_head' = render 'dashboard/snippets_head'
.gray-content-block .nav-block
.pull-right .controls
= link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do = link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do
= icon('plus') = icon('plus')
New Snippet New Snippet
.btn-group.btn-group-next.snippet-scope-menu .nav-links.snippet-scope-menu
= link_to dashboard_snippets_path, class: "btn btn-default #{"active" unless params[:scope]}" do %li{ class: ("active" unless params[:scope]) }
= link_to dashboard_snippets_path do
All All
%span.badge %span.badge
= current_user.snippets.count = current_user.snippets.count
= link_to dashboard_snippets_path(scope: 'are_private'), class: "btn btn-default #{"active" if params[:scope] == "are_private"}" do %li{ class: ("active" if params[:scope] == "are_private") }
= link_to dashboard_snippets_path(scope: 'are_private') do
Private Private
%span.badge %span.badge
= current_user.snippets.are_private.count = current_user.snippets.are_private.count
= link_to dashboard_snippets_path(scope: 'are_internal'), class: "btn btn-default #{"active" if params[:scope] == "are_internal"}" do %li{ class: ("active" if params[:scope] == "are_internal") }
= link_to dashboard_snippets_path(scope: 'are_internal') do
Internal Internal
%span.badge %span.badge
= current_user.snippets.are_internal.count = current_user.snippets.are_internal.count
= link_to dashboard_snippets_path(scope: 'are_public'), class: "btn btn-default #{"active" if params[:scope] == "are_public"}" do %li{ class: ("active" if params[:scope] == "are_public") }
= link_to dashboard_snippets_path(scope: 'are_public') do
Public Public
%span.badge %span.badge
= current_user.snippets.are_public.count = current_user.snippets.are_public.count
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
%h3 Sign in %h3 Sign in
.login-body .login-body
- if form_based_providers.any? - if form_based_providers.any?
%ul.nav.nav-tabs %ul.nav-links
- if crowd_enabled? - if crowd_enabled?
%li.active %li.active
= link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab' = link_to "Crowd", "#tab-crowd", 'data-toggle' => 'tab'
......
- header_title group_title(@group, "Settings", edit_group_path(@group)) - header_title group_title(@group, "Settings", edit_group_path(@group))
- @blank_container = true - @blank_container = true
.panel.panel-default .panel.panel-default.prepend-top-default
.panel-heading .panel-heading
Group settings Group settings
.panel-body .panel-body
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- header_title group_title(@group, "Members", group_group_members_path(@group)) - header_title group_title(@group, "Members", group_group_members_path(@group))
- @blank_container = true - @blank_container = true
.group-members-page .group-members-page.prepend-top-default
- if current_user && current_user.can?(:admin_group_member, @group) - if current_user && current_user.can?(:admin_group_member, @group)
.panel.panel-default .panel.panel-default
.panel-heading .panel-heading
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#{@milestone.open_items_count} open #{@milestone.open_items_count} open
= milestone_progress_bar(@milestone) = milestone_progress_bar(@milestone)
%ul.center-top-menu.no-top.no-bottom %ul.nav-links.no-top.no-bottom
%li.active %li.active
= link_to '#tab-issues', 'data-toggle' => 'tab' do = link_to '#tab-issues', 'data-toggle' => 'tab' do
Issues Issues
......
- page_title "Projects" - page_title "Projects"
- header_title group_title(@group, "Projects", projects_group_path(@group)) - header_title group_title(@group, "Projects", projects_group_path(@group))
.panel.panel-default .panel.panel-default.prepend-top-default
.panel-heading .panel-heading
%strong= @group.name %strong= @group.name
projects: projects:
......
- @no_container = true
- unless can?(current_user, :read_group, @group) - unless can?(current_user, :read_group, @group)
- @disable_search_panel = true - @disable_search_panel = true
...@@ -25,8 +27,8 @@ ...@@ -25,8 +27,8 @@
.cover-desc.description .cover-desc.description
= markdown(@group.description, pipeline: :description) = markdown(@group.description, pipeline: :description)
- if can?(current_user, :read_group, @group)
%ul.center-top-menu.no-top %ul.nav-links
%li.active %li.active
= link_to "#activity", 'data-toggle' => 'tab' do = link_to "#activity", 'data-toggle' => 'tab' do
Activity Activity
...@@ -35,9 +37,11 @@ ...@@ -35,9 +37,11 @@
= link_to "#projects", 'data-toggle' => 'tab' do = link_to "#projects", 'data-toggle' => 'tab' do
Projects Projects
- if can?(current_user, :read_group, @group)
%div{ class: container_class }
.tab-content .tab-content
.tab-pane.active#activity .tab-pane.active#activity
.gray-content-block.activity-filter-block .activity-filter-block
- if current_user - if current_user
= render "events/event_last_push", event: @last_push = render "events/event_last_push", event: @last_push
...@@ -50,5 +54,5 @@ ...@@ -50,5 +54,5 @@
= render "projects", projects: @projects = render "projects", projects: @projects
- else - else
%p.center-top-menu.no-top %p.nav-links.no-top
No projects to show No projects to show
...@@ -139,26 +139,9 @@ ...@@ -139,26 +139,9 @@
%h2#navs Navigation %h2#navs Navigation
%h4 %h4
%code .center-top-menu %code .nav-links
.example .example
%ul.center-top-menu %ul.nav-links
%li.active
%a Open
%li
%a Closed
%h4
%code .btn-group.btn-group-next
.example
%div.btn-group.btn-group-next
%a.btn.active Open
%a.btn Closed
%h4
%code .nav.nav-tabs
.example
%ul.nav.nav-tabs
%li.active %li.active
%a Open %a Open
%li %li
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
.content-wrapper .content-wrapper
= render "layouts/flash" = render "layouts/flash"
= yield :flash_message = yield :flash_message
%div{ class: container_class } %div{ class: (container_class unless @no_container) }
.content .content
.clearfix .clearfix
= yield = yield
...@@ -44,6 +44,10 @@ ...@@ -44,6 +44,10 @@
%br %br
-# Don't link the host is the line below, one link in the email is easier to quickly click than two. -# Don't link the host is the line below, one link in the email is easier to quickly click than two.
You're receiving this email because of your account on #{Gitlab.config.gitlab.host}. You're receiving this email because of your account on #{Gitlab.config.gitlab.host}.
If you'd like to receive fewer emails, you can adjust your notification settings. If you'd like to receive fewer emails, you can
- if @sent_notification && @sent_notification.unsubscribable?
= link_to "unsubscribe", unsubscribe_sent_notification_url(@sent_notification)
from this thread or
adjust your notification settings.
= email_action @target_url = email_action @target_url
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.alert.alert-info .alert.alert-info
Some options are unavailable for LDAP accounts Some options are unavailable for LDAP accounts
.account-page .account-page.prepend-top-default
.panel.panel-default.update-token .panel.panel-default.update-token
.panel-heading .panel-heading
Reset Private token Reset Private token
......
.gray-content-block.activity-filter-block .nav-block.activity-filter-block
- if current_user - if current_user
.pull-right .controls
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'btn rss-btn' do = link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), title: "Feed", class: 'btn rss-btn' do
%i.fa.fa-rss %i.fa.fa-rss
......
#tree-holder.tree-holder.clearfix #tree-holder.tree-holder.clearfix
.gray-content-block.second-block .nav-block
= render 'projects/tree/tree_header', tree: @tree = render 'projects/tree/tree_header', tree: @tree
= render 'projects/tree/tree_content', tree: @tree = render 'projects/tree/tree_content', tree: @tree
......
...@@ -44,9 +44,12 @@ ...@@ -44,9 +44,12 @@
= render 'projects/buttons/star' = render 'projects/buttons/star'
= render 'projects/buttons/fork' = render 'projects/buttons/fork'
.clone-row
.project-clone-holder
= render "shared/clone_panel" = render "shared/clone_panel"
.split-repo-buttons .split-repo-buttons
.btn-group.pull-left
= render "projects/buttons/download" = render "projects/buttons/download"
= render 'projects/buttons/dropdown' = render 'projects/buttons/dropdown'
......
.md-area .md-area
.md-header.clearfix .md-header.clearfix
%ul.center-top-menu %ul.nav-links
%li.active %li.active
%a.js-md-write-button(href="#md-write-holder" tabindex="-1") %a.js-md-write-button(href="#md-write-holder" tabindex="-1")
Write Write
......
.zennable .zennable
.zen-backdrop .zen-backdrop
- classes << ' js-gfm-input markdown-area' - classes << ' js-gfm-input js-autosize markdown-area'
- if defined?(f) && f - if defined?(f) && f
= f.text_area attr, class: classes = f.text_area attr, class: classes
- else - else
......
%tr{ class: 'tree-item' }
%td.tree-item-file-name
= tree_icon('folder', '755', directory.name)
%span.str-truncated
= link_to directory.name, browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: directory.path)
%td
%td
%tr{ class: 'tree-item' }
%td.tree-item-file-name
= tree_icon('file', '664', file.name)
%span.str-truncated
= file.name
%td
= number_to_human_size(file.metadata[:size], precision: 2)
%td
= link_to file_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: file.path),
class: 'btn btn-xs btn-default artifact-download' do
= icon('download')
- page_title 'Artifacts', "#{@build.name} (##{@build.id})", 'Builds'
= render 'projects/builds/header_title'
#tree-holder.tree-holder
.gray-content-block.top-block.clearfix
.pull-right
= link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build),
class: 'btn btn-default' do
= icon('download')
Download artifacts archive
%div.tree-content-holder
.table-holder
%table.table.tree-table.table-striped
%thead
%tr
%th Name
%th Size
%th Download
= render partial: 'tree_directory', collection: @entry.directories(parent: true), as: :directory
= render partial: 'tree_file', collection: @entry.files, as: :file
- if @entry.empty?
.center Empty
.gray-content-block.top-block .nav-block
.tree-ref-holder .tree-ref-holder
= render 'shared/ref_switcher', destination: 'blob', path: @path = render 'shared/ref_switcher', destination: 'blob', path: @path
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
= render "header_title" = render "header_title"
.file-editor .file-editor
%ul.center-top-menu.no-bottom.js-edit-mode %ul.nav-links.no-bottom.js-edit-mode
%li.active %li.active
= link_to '#editor' do = link_to '#editor' do
= icon('edit') = icon('edit')
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
- if @all_builds.running_or_pending.any? - if @all_builds.running_or_pending.any?
= link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
%ul.center-top-menu %ul.nav-links
%li{class: ('active' if @scope.nil?)} %li{class: ('active' if @scope.nil?)}
= link_to project_builds_path(@project) do = link_to project_builds_path(@project) do
All All
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#up-build-trace #up-build-trace
- if @commit.matrix_for_ref?(@build.ref) - if @commit.matrix_for_ref?(@build.ref)
%ul.center-top-menu.no-top.no-bottom %ul.nav-links.no-top.no-bottom
- @commit.latest_builds_for_ref(@build.ref).each do |build| - @commit.latest_builds_for_ref(@build.ref).each do |build|
%li{class: ('active' if build == @build) } %li{class: ('active' if build == @build) }
= link_to namespace_project_build_path(@project.namespace, @project, build) do = link_to namespace_project_build_path(@project.namespace, @project, build) do
...@@ -89,9 +89,15 @@ ...@@ -89,9 +89,15 @@
Test coverage Test coverage
%h1 #{@build.coverage}% %h1 #{@build.coverage}%
- if current_user && can?(current_user, :download_build_artifacts, @project) && @build.download_url - if current_user && can?(current_user, :read_build_artifacts, @project) && @build.artifacts?
.build-widget.center
= link_to "Download artifacts", @build.download_url, class: 'btn btn-sm btn-primary' .build-widget.artifacts
%h4.title Build artifacts
.center
.btn-group{ role: :group }
= link_to "Download", @build.artifacts_download_url, class: 'btn btn-sm btn-primary'
- if @build.artifacts_browser_supported?
= link_to "Browse", @build.artifacts_browse_url, class: 'btn btn-sm btn-primary'
.build-widget .build-widget
%h4.title %h4.title
......
- if current_user - if current_user
%span.dropdown .btn-group
%a.dropdown-new.btn.btn-new{href: '#', "data-toggle" => "dropdown"} %a.btn.dropdown-toggle{href: '#', "data-toggle" => "dropdown"}
= icon('plus') = icon('plus')
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- if can?(current_user, :create_issue, @project) - if can?(current_user, :create_issue, @project)
......
%ul.center-top-menu.no-top.no-bottom.commit-ci-menu %ul.nav-links.no-top.no-bottom.commit-ci-menu
= nav_link(path: 'commit#show') do = nav_link(path: 'commit#show') do
= link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do = link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Changes Changes
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
.commit-info-row.branches .commit-info-row.branches
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
.commit-box.gray-content-block.middle-block .commit-box.content-block
%h3.commit-title %h3.commit-title
= markdown escape_once(@commit.title), pipeline: :single_line = markdown escape_once(@commit.title), pipeline: :single_line
- if @commit.description.present? - if @commit.description.present?
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
- page_description @commit.description - page_description @commit.description
= render "projects/commits/header_title" = render "projects/commits/header_title"
= render "commit_box"
.prepend-top-default
= render "commit_box"
- if @ci_commit - if @ci_commit
= render "ci_menu" = render "ci_menu"
- else - else
......
...@@ -66,8 +66,8 @@ ...@@ -66,8 +66,8 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :download_build_artifacts, commit_status.project) && commit_status.download_url - if current_user && can?(current_user, :read_build_artifacts, commit_status.project) && commit_status.artifacts?
= link_to commit_status.download_url, title: 'Download artifacts' do = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, commit_status.project) - if current_user && can?(current_user, :manage_builds, commit_status.project)
- if commit_status.active? - if commit_status.active?
......
%ul.center-top-menu %ul.nav-links
= nav_link(controller: [:commit, :commits]) do = nav_link(controller: [:commit, :commits]) do
= link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
Commits Commits
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
= render "head" = render "head"
.gray-content-block .gray-content-block.second-block
.tree-ref-holder .tree-ref-holder
= render 'shared/ref_switcher', destination: 'commits' = render 'shared/ref_switcher', destination: 'commits'
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- diff_files = safe_diff_files(diffs) - diff_files = safe_diff_files(diffs)
.gray-content-block.middle-block.oneline-block .content-block.oneline-block
.inline-parallel-buttons .inline-parallel-buttons
.btn-group .btn-group
= inline_diff_btn = inline_diff_btn
......
- @blank_container = true - @blank_container = true
.project-edit-container .project-edit-container.prepend-top-default
.project-edit-errors .project-edit-errors
.project-edit-content .project-edit-content
.panel.panel-default .panel.panel-default
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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