Commit 0378c5b8 authored by Fatih Acet's avatar Fatih Acet

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into sidebar-expand-collapse

parents aa2a7dad 380966e8
require: rubocop-rspec
AllCops: AllCops:
TargetRubyVersion: 2.1 TargetRubyVersion: 2.1
# Cop names are not displayed in offense messages by default. Change behavior # Cop names are not displayed in offense messages by default. Change behavior
...@@ -57,7 +59,7 @@ Style/AndOr: ...@@ -57,7 +59,7 @@ Style/AndOr:
# Use `Array#join` instead of `Array#*`. # Use `Array#join` instead of `Array#*`.
Style/ArrayJoin: Style/ArrayJoin:
Enabled: false Enabled: true
# Use only ascii symbols in comments. # Use only ascii symbols in comments.
Style/AsciiComments: Style/AsciiComments:
...@@ -69,7 +71,7 @@ Style/AsciiIdentifiers: ...@@ -69,7 +71,7 @@ Style/AsciiIdentifiers:
# Checks for uses of Module#attr. # Checks for uses of Module#attr.
Style/Attr: Style/Attr:
Enabled: false Enabled: true
# Avoid the use of BEGIN blocks. # Avoid the use of BEGIN blocks.
Style/BeginBlock: Style/BeginBlock:
...@@ -81,7 +83,7 @@ Style/BarePercentLiterals: ...@@ -81,7 +83,7 @@ Style/BarePercentLiterals:
# Do not use block comments. # Do not use block comments.
Style/BlockComments: Style/BlockComments:
Enabled: false Enabled: true
# Put end statement of multiline block on its own line. # Put end statement of multiline block on its own line.
Style/BlockEndNewline: Style/BlockEndNewline:
...@@ -122,7 +124,7 @@ Style/ClassCheck: ...@@ -122,7 +124,7 @@ Style/ClassCheck:
# Use self when defining module/class methods. # Use self when defining module/class methods.
Style/ClassMethods: Style/ClassMethods:
Enabled: false Enabled: true
# Avoid the use of class variables. # Avoid the use of class variables.
Style/ClassVars: Style/ClassVars:
...@@ -216,7 +218,7 @@ Style/EmptyLiteral: ...@@ -216,7 +218,7 @@ Style/EmptyLiteral:
# Avoid the use of END blocks. # Avoid the use of END blocks.
Style/EndBlock: Style/EndBlock:
Enabled: false Enabled: true
# Use Unix-style line endings. # Use Unix-style line endings.
Style/EndOfLine: Style/EndOfLine:
...@@ -224,7 +226,7 @@ Style/EndOfLine: ...@@ -224,7 +226,7 @@ Style/EndOfLine:
# Favor the use of Fixnum#even? && Fixnum#odd? # Favor the use of Fixnum#even? && Fixnum#odd?
Style/EvenOdd: Style/EvenOdd:
Enabled: false Enabled: true
# Do not use unnecessary spacing. # Do not use unnecessary spacing.
Style/ExtraSpacing: Style/ExtraSpacing:
...@@ -232,11 +234,16 @@ Style/ExtraSpacing: ...@@ -232,11 +234,16 @@ Style/ExtraSpacing:
# Use snake_case for source file names. # Use snake_case for source file names.
Style/FileName: Style/FileName:
Enabled: false Enabled: true
# Checks for a line break before the first parameter in a multi-line method
# parameter definition.
Style/FirstMethodParameterLineBreak:
Enabled: true
# Checks for flip flops. # Checks for flip flops.
Style/FlipFlop: Style/FlipFlop:
Enabled: false Enabled: true
# Checks use of for or each in multiline loops. # Checks use of for or each in multiline loops.
Style/For: Style/For:
...@@ -248,7 +255,7 @@ Style/FormatString: ...@@ -248,7 +255,7 @@ Style/FormatString:
# Do not introduce global variables. # Do not introduce global variables.
Style/GlobalVars: Style/GlobalVars:
Enabled: false Enabled: true
# Check for conditionals that can be replaced with guard clauses. # Check for conditionals that can be replaced with guard clauses.
Style/GuardClause: Style/GuardClause:
...@@ -269,7 +276,7 @@ Style/IfUnlessModifier: ...@@ -269,7 +276,7 @@ Style/IfUnlessModifier:
# Do not use if x; .... Use the ternary operator instead. # Do not use if x; .... Use the ternary operator instead.
Style/IfWithSemicolon: Style/IfWithSemicolon:
Enabled: false Enabled: true
# Checks that conditional statements do not have an identical line at the # Checks that conditional statements do not have an identical line at the
# end of each branch, which can validly be moved out of the conditional. # end of each branch, which can validly be moved out of the conditional.
...@@ -307,7 +314,7 @@ Style/Lambda: ...@@ -307,7 +314,7 @@ Style/Lambda:
# Use lambda.call(...) instead of lambda.(...). # Use lambda.call(...) instead of lambda.(...).
Style/LambdaCall: Style/LambdaCall:
Enabled: false Enabled: true
# Comments should start with a space. # Comments should start with a space.
Style/LeadingCommentSpace: Style/LeadingCommentSpace:
...@@ -327,7 +334,7 @@ Style/MethodDefParentheses: ...@@ -327,7 +334,7 @@ Style/MethodDefParentheses:
# Use the configured style when naming methods. # Use the configured style when naming methods.
Style/MethodName: Style/MethodName:
Enabled: false Enabled: true
# Checks for usage of `extend self` in modules. # Checks for usage of `extend self` in modules.
Style/ModuleFunction: Style/ModuleFunction:
...@@ -368,6 +375,11 @@ Style/MultilineMethodCallBraceLayout: ...@@ -368,6 +375,11 @@ Style/MultilineMethodCallBraceLayout:
Style/MultilineMethodCallIndentation: Style/MultilineMethodCallIndentation:
Enabled: false Enabled: false
# Checks that the closing brace in a method definition is symmetrical with
# respect to the opening brace and the method parameters.
Style/MultilineMethodDefinitionBraceLayout:
Enabled: false
# Checks indentation of binary operations that span more than one line. # Checks indentation of binary operations that span more than one line.
Style/MultilineOperationIndentation: Style/MultilineOperationIndentation:
Enabled: false Enabled: false
...@@ -390,7 +402,7 @@ Style/NegatedWhile: ...@@ -390,7 +402,7 @@ Style/NegatedWhile:
# Avoid using nested modifiers. # Avoid using nested modifiers.
Style/NestedModifier: Style/NestedModifier:
Enabled: false Enabled: true
# Parenthesize method calls which are nested inside the argument list of # Parenthesize method calls which are nested inside the argument list of
# another parenthesized method call. # another parenthesized method call.
...@@ -427,7 +439,7 @@ Style/OneLineConditional: ...@@ -427,7 +439,7 @@ Style/OneLineConditional:
# When defining binary operators, name the argument other. # When defining binary operators, name the argument other.
Style/OpMethod: Style/OpMethod:
Enabled: false Enabled: true
# Check for simple usages of parallel assignment. It will only warn when # Check for simple usages of parallel assignment. It will only warn when
# the number of variables matches on both sides of the assignment. # the number of variables matches on both sides of the assignment.
...@@ -507,7 +519,8 @@ Style/Semicolon: ...@@ -507,7 +519,8 @@ Style/Semicolon:
# Checks for proper usage of fail and raise. # Checks for proper usage of fail and raise.
Style/SignalException: Style/SignalException:
Enabled: false EnforcedStyle: only_raise
Enabled: true
# Enforces the names of some block params. # Enforces the names of some block params.
Style/SingleLineBlockParams: Style/SingleLineBlockParams:
...@@ -532,11 +545,11 @@ Style/SpaceAfterMethodName: ...@@ -532,11 +545,11 @@ Style/SpaceAfterMethodName:
# Tracks redundant space after the ! operator. # Tracks redundant space after the ! operator.
Style/SpaceAfterNot: Style/SpaceAfterNot:
Enabled: false Enabled: true
# Use spaces after semicolons. # Use spaces after semicolons.
Style/SpaceAfterSemicolon: Style/SpaceAfterSemicolon:
Enabled: false Enabled: true
# Checks that the equals signs in parameter default assignments have or don't # Checks that the equals signs in parameter default assignments have or don't
# have surrounding space depending on configuration. # have surrounding space depending on configuration.
...@@ -570,7 +583,7 @@ Style/SpaceBeforeFirstArg: ...@@ -570,7 +583,7 @@ Style/SpaceBeforeFirstArg:
# No spaces before semicolons. # No spaces before semicolons.
Style/SpaceBeforeSemicolon: Style/SpaceBeforeSemicolon:
Enabled: false Enabled: true
# Checks that block braces have or don't have surrounding space. # Checks that block braces have or don't have surrounding space.
# For blocks taking parameters, checks that the left brace has or doesn't # For blocks taking parameters, checks that the left brace has or doesn't
...@@ -592,11 +605,12 @@ Style/SpaceInsideParens: ...@@ -592,11 +605,12 @@ Style/SpaceInsideParens:
# No spaces inside range literals. # No spaces inside range literals.
Style/SpaceInsideRangeLiteral: Style/SpaceInsideRangeLiteral:
Enabled: false Enabled: true
# Checks for padding/surrounding spaces inside string interpolation. # Checks for padding/surrounding spaces inside string interpolation.
Style/SpaceInsideStringInterpolation: Style/SpaceInsideStringInterpolation:
Enabled: false EnforcedStyle: no_space
Enabled: true
# Avoid Perl-style global variables. # Avoid Perl-style global variables.
Style/SpecialGlobalVars: Style/SpecialGlobalVars:
...@@ -604,7 +618,8 @@ Style/SpecialGlobalVars: ...@@ -604,7 +618,8 @@ Style/SpecialGlobalVars:
# Check for the usage of parentheses around stabby lambda arguments. # Check for the usage of parentheses around stabby lambda arguments.
Style/StabbyLambdaParentheses: Style/StabbyLambdaParentheses:
Enabled: false EnforcedStyle: require_parentheses
Enabled: true
# Checks if uses of quotes match the configured preference. # Checks if uses of quotes match the configured preference.
Style/StringLiterals: Style/StringLiterals:
...@@ -617,7 +632,9 @@ Style/StringLiteralsInInterpolation: ...@@ -617,7 +632,9 @@ Style/StringLiteralsInInterpolation:
# Checks if configured preferred methods are used over non-preferred. # Checks if configured preferred methods are used over non-preferred.
Style/StringMethods: Style/StringMethods:
Enabled: false PreferredMethods:
intern: to_sym
Enabled: true
# Use %i or %I for arrays of symbols. # Use %i or %I for arrays of symbols.
Style/SymbolArray: Style/SymbolArray:
...@@ -675,15 +692,16 @@ Style/UnneededPercentQ: ...@@ -675,15 +692,16 @@ Style/UnneededPercentQ:
# Don't interpolate global, instance and class variables directly in strings. # Don't interpolate global, instance and class variables directly in strings.
Style/VariableInterpolation: Style/VariableInterpolation:
Enabled: false Enabled: true
# Use the configured style when naming variables. # Use the configured style when naming variables.
Style/VariableName: Style/VariableName:
Enabled: false EnforcedStyle: snake_case
Enabled: true
# Use when x then ... for one-line cases. # Use when x then ... for one-line cases.
Style/WhenThen: Style/WhenThen:
Enabled: false Enabled: true
# Checks for redundant do after while or until. # Checks for redundant do after while or until.
Style/WhileUntilDo: Style/WhileUntilDo:
...@@ -691,7 +709,7 @@ Style/WhileUntilDo: ...@@ -691,7 +709,7 @@ Style/WhileUntilDo:
# Favor modifier while/until usage when you have a single-line body. # Favor modifier while/until usage when you have a single-line body.
Style/WhileUntilModifier: Style/WhileUntilModifier:
Enabled: false Enabled: true
# Use %w or %W for arrays of words. # Use %w or %W for arrays of words.
Style/WordArray: Style/WordArray:
...@@ -1071,3 +1089,65 @@ Rails/TimeZone: ...@@ -1071,3 +1089,65 @@ Rails/TimeZone:
# Use validates :attribute, hash of validations. # Use validates :attribute, hash of validations.
Rails/Validation: Rails/Validation:
Enabled: false Enabled: false
##################### RSpec ##################################
# Check that instances are not being stubbed globally.
RSpec/AnyInstance:
Enabled: false
# Check that the first argument to the top level describe is the tested class or
# module.
RSpec/DescribeClass:
Enabled: false
# Use `described_class` for tested class / module.
RSpec/DescribeMethod:
Enabled: false
# Checks that the second argument to top level describe is the tested method
# name.
RSpec/DescribedClass:
Enabled: false
# Checks for long example.
RSpec/ExampleLength:
Enabled: false
Max: 5
# Do not use should when describing your tests.
RSpec/ExampleWording:
Enabled: false
CustomTransform:
be: is
have: has
not: does not
IgnoredWords: []
# Checks the file and folder naming of the spec file.
RSpec/FilePath:
Enabled: false
CustomTransform:
RuboCop: rubocop
RSpec: rspec
# Checks if there are focused specs.
RSpec/Focus:
Enabled: true
# Checks for the usage of instance variables.
RSpec/InstanceVariable:
Enabled: false
# Checks for multiple top-level describes.
RSpec/MultipleDescribes:
Enabled: false
# Enforces the usage of the same method on all negative message expectations.
RSpec/NotToNot:
EnforcedStyle: not_to
Enabled: true
# Prefer using verifying doubles over normal doubles.
RSpec/VerifiedDoubles:
Enabled: false
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.8.2 (unreleased) v 8.9.0 (unreleased)
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources - Redesign navigation for project pages
- Fix Error 500 in CI charts by gracefully handling commits with no durations - Use gitlab-shell v3.0.0
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
- Changed the Slack build message to use the singular duration if necessary (Aran Koning)
- Fix issues filter when ordering by milestone
- Todos will display target state if issuable target is 'Closed' or 'Merged'
v 8.8.2
- Added remove due date button. !4209
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242
- Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245
- Fix table UI on CI builds page. !4249
- Fix backups if registry is disabled. !4263
- Fixed issue with merge button color. !4211
- Fixed issue with enter key selecting wrong option in dropdown. !4210
- When creating a .gitignore file a dropdown with templates will be provided. !4075
- Fix concurrent request when updating build log in browser. !4183
v 8.8.1 v 8.8.1
- Add documentation for the "Health Check" feature - Add documentation for the "Health Check" feature
- Allow anonymous users to access a public project's pipelines - Allow anonymous users to access a public project's pipelines !4233
- Fix MySQL compatibility in zero downtime migrations helpers - Fix MySQL compatibility in zero downtime migrations helpers
- Fix the CI login to Container Registry (the gitlab-ci-token user) - Fix the CI login to Container Registry (the gitlab-ci-token user)
......
...@@ -294,6 +294,7 @@ group :development, :test do ...@@ -294,6 +294,7 @@ group :development, :test do
gem 'spring-commands-teaspoon', '~> 0.0.2' gem 'spring-commands-teaspoon', '~> 0.0.2'
gem 'rubocop', '~> 0.40.0', require: false gem 'rubocop', '~> 0.40.0', require: false
gem 'rubocop-rspec', '~> 1.5.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.11.0', require: false gem 'simplecov', '~> 0.11.0', require: false
......
...@@ -692,6 +692,8 @@ GEM ...@@ -692,6 +692,8 @@ GEM
rainbow (>= 1.99.1, < 3.0) rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
rubocop-rspec (1.5.0)
rubocop (>= 0.40.0)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-progressbar (1.8.1) ruby-progressbar (1.8.1)
...@@ -1016,6 +1018,7 @@ DEPENDENCIES ...@@ -1016,6 +1018,7 @@ DEPENDENCIES
rspec-rails (~> 3.4.0) rspec-rails (~> 3.4.0)
rspec-retry rspec-retry
rubocop (~> 0.40.0) rubocop (~> 0.40.0)
rubocop-rspec (~> 1.5.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 5.0.0) sass-rails (~> 5.0.0)
......
8.8.0-pre 8.9.0-pre
...@@ -28,12 +28,15 @@ class CiBuild ...@@ -28,12 +28,15 @@ class CiBuild
# #
CiBuild.interval = setInterval => CiBuild.interval = setInterval =>
if window.location.href.split("#").first() is build_url if window.location.href.split("#").first() is build_url
last_state = @state
$.ajax $.ajax
url: build_url + "/trace.json?state=" + encodeURIComponent(@state) url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
dataType: "json" dataType: "json"
success: (log) => success: (log) =>
return unless last_state is @state
if log.state and log.status is "running"
@state = log.state @state = log.state
if log.status is "running"
if log.append if log.append
$('.fa-refresh').before log.html $('.fa-refresh').before log.html
else else
......
...@@ -16,7 +16,6 @@ class Dispatcher ...@@ -16,7 +16,6 @@ class Dispatcher
shortcut_handler = null shortcut_handler = null
switch page switch page
when 'projects:issues:index' when 'projects:issues:index'
Issues.init()
Issuable.init() Issuable.init()
shortcut_handler = new ShortcutsNavigation() shortcut_handler = new ShortcutsNavigation()
when 'projects:issues:show' when 'projects:issues:show'
...@@ -119,7 +118,7 @@ class Dispatcher ...@@ -119,7 +118,7 @@ class Dispatcher
new UsersSelect() new UsersSelect()
when 'projects' when 'projects'
new NamespaceSelect() new NamespaceSelect()
when 'dashboard' when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation() shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles' when 'profiles'
new Profile() new Profile()
......
issuable_created = false
@Issuable = @Issuable =
init: -> init: ->
unless issuable_created
issuable_created = true
Issuable.initTemplates() Issuable.initTemplates()
Issuable.initSearch() Issuable.initSearch()
Issuable.initChecks()
initTemplates: -> initTemplates: ->
Issuable.labelRow = _.template( Issuable.labelRow = _.template(
...@@ -19,7 +23,16 @@ ...@@ -19,7 +23,16 @@
.on 'keyup', -> .on 'keyup', ->
clearTimeout(@timer) clearTimeout(@timer)
@timer = setTimeout( -> @timer = setTimeout( ->
Issuable.filterResults $('#issue_search_form') $search = $('#issue_search')
$form = $('.js-filter-form')
$input = $("input[name='#{$search.attr('name')}']", $form)
if $input.length is 0
$form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>"
else
$input.val $search.val()
Issuable.filterResults $form
, 500) , 500)
toggleLabelFilters: -> toggleLabelFilters: ->
...@@ -59,15 +72,22 @@ ...@@ -59,15 +72,22 @@
dataType: "json" dataType: "json"
reload: -> reload: ->
if Issues.created if Issuable.created
Issues.initChecks() Issuable.initChecks()
$('#filter_issue_search').val($('#issue_search').val()) $('#filter_issue_search').val($('#issue_search').val())
initChecks: ->
$('.check_all_issues').on 'click', ->
$('.selected_issue').prop('checked', @checked)
Issuable.checkChanged()
$('.selected_issue').on 'change', Issuable.checkChanged
updateStateFilters: -> updateStateFilters: ->
stateFilters = $('.issues-state-filters') stateFilters = $('.issues-state-filters, .dropdown-menu-sort')
newParams = {} newParams = {}
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search'] paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search', 'issue_search']
for paramKey in paramKeys for paramKey in paramKeys
newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or '' newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
...@@ -82,3 +102,17 @@ ...@@ -82,3 +102,17 @@
else else
newUrl = gl.utils.mergeUrlParams(newParams, initialUrl) newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
$(this).attr 'href', newUrl $(this).attr 'href', newUrl
checkChanged: ->
checked_issues = $('.selected_issue:checked')
if checked_issues.length > 0
ids = $.map checked_issues, (value) ->
$(value).data('id')
$('#update_issues_ids').val ids
$('.issues-other-filters').hide()
$('.issues_bulk_update').show()
else
$('#update_issues_ids').val []
$('.issues_bulk_update').hide()
$('.issues-other-filters').show()
@Issues =
init: ->
Issues.created = true
Issues.initChecks()
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
t = $(this)
totalIssues = undefined
reopen = t.hasClass("reopen_issue")
$(".issue_counter").each ->
issue = $(this)
totalIssues = parseInt($(this).html(), 10)
if reopen and issue.closest(".main_menu").length
$(this).html totalIssues + 1
else
$(this).html totalIssues - 1
initChecks: ->
$(".check_all_issues").click ->
$(".selected_issue").prop("checked", @checked)
Issues.checkChanged()
$(".selected_issue").bind "change", Issues.checkChanged
checkChanged: ->
checked_issues = $(".selected_issue:checked")
if checked_issues.length > 0
ids = []
$.each checked_issues, (index, value) ->
ids.push $(value).attr("data-id")
$("#update_issues_ids").val ids
$(".issues-other-filters").hide()
$(".issues_bulk_update").show()
else
$("#update_issues_ids").val []
$(".issues_bulk_update").hide()
$(".issues-other-filters").show()
...@@ -26,10 +26,19 @@ ...@@ -26,10 +26,19 @@
newUrl = decodeURIComponent(url) newUrl = decodeURIComponent(url)
for paramName, paramValue of params for paramName, paramValue of params
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)" pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
if url.search(pattern) >= 0 if not paramValue?
newUrl = newUrl.replace pattern, ''
else if url.search(pattern) isnt -1
newUrl = newUrl.replace pattern, "$1#{paramValue}$2" newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
else else
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}" newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
# Remove a trailing ampersand
lastChar = newUrl[newUrl.length - 1]
if lastChar is '&'
newUrl = newUrl.slice 0, -1
newUrl newUrl
# removes parameter query string from url. returns the modified url # removes parameter query string from url. returns the modified url
......
...@@ -75,6 +75,9 @@ class @MergeRequestTabs ...@@ -75,6 +75,9 @@ class @MergeRequestTabs
@loadDiff($target.attr('href')) @loadDiff($target.attr('href'))
if bp? and bp.getBreakpointSize() isnt 'lg' if bp? and bp.getBreakpointSize() isnt 'lg'
@shrinkView() @shrinkView()
navBarHeight = $('.navbar-gitlab').outerHeight()
$.scrollTo(".merge-request-details .merge-request-tabs", offset: -navBarHeight)
else if action == 'builds' else if action == 'builds'
@loadBuilds($target.attr('href')) @loadBuilds($target.attr('href'))
@expandView() @expandView()
......
...@@ -106,6 +106,7 @@ class @MergeRequestWidget ...@@ -106,6 +106,7 @@ class @MergeRequestWidget
@firstCICheck = false @firstCICheck = false
showCIStatus: (state) -> showCIStatus: (state) ->
return if not state?
$('.ci_widget').hide() $('.ci_widget').hide()
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"] allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
if state in allowed_states if state in allowed_states
...@@ -126,6 +127,6 @@ class @MergeRequestWidget ...@@ -126,6 +127,6 @@ class @MergeRequestWidget
$('.ci_widget:visible .ci-coverage').text(text) $('.ci_widget:visible .ci-coverage').text(text)
setMergeButtonClass: (css_class) -> setMergeButtonClass: (css_class) ->
$('.js-merge-button') $('.js-merge-button,.accept-action .dropdown-toggle')
.removeClass('btn-danger btn-warning btn-create') .removeClass('btn-danger btn-warning btn-create')
.addClass(css_class) .addClass(css_class)
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
class @ShortcutsDashboardNavigation extends Shortcuts class @ShortcutsDashboardNavigation extends Shortcuts
constructor: -> constructor: ->
super() super()
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity')) Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues')) Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests')) Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects')) Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects'))
@findAndFollowLink: (selector) -> @findAndFollowLink: (selector) ->
link = $(selector).attr('href') link = $(selector).attr('href')
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
&.s32 { font-size: 20px; line-height: 32px; } &.s32 { font-size: 20px; line-height: 32px; }
&.s40 { font-size: 16px; line-height: 40px; } &.s40 { font-size: 16px; line-height: 40px; }
&.s60 { font-size: 32px; line-height: 60px; } &.s60 { font-size: 32px; line-height: 60px; }
&.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 90px; } &.s90 { font-size: 36px; line-height: 90px; }
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
&.s140 { font-size: 72px; line-height: 140px; } &.s140 { font-size: 72px; line-height: 140px; }
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
background-color: $background-color; background-color: $background-color;
padding: $gl-padding; padding: $gl-padding;
margin-bottom: 0; margin-bottom: 0;
border-top: 1px solid $border-color; border-top: 1px solid $white-dark;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $white-dark;
color: $gl-gray; color: $gl-gray;
&.oneline-block { &.oneline-block {
...@@ -110,9 +110,9 @@ ...@@ -110,9 +110,9 @@
.cover-title { .cover-title {
color: $gl-header-color; color: $gl-header-color;
margin: 0; margin: 0;
font-size: 23px; font-size: 24px;
font-weight: normal; font-weight: normal;
margin: 16px 0 5px; margin-bottom: 5px;
color: #4c4e54; color: #4c4e54;
font-size: 23px; font-size: 23px;
line-height: 1.1; line-height: 1.1;
...@@ -137,7 +137,6 @@ ...@@ -137,7 +137,6 @@
} }
.cover-desc { .cover-desc {
padding: 0 $gl-padding 3px;
color: $gl-text-color; color: $gl-text-color;
&.username:last-child { &.username:last-child {
...@@ -205,7 +204,7 @@ ...@@ -205,7 +204,7 @@
.content-block { .content-block {
padding: $gl-padding 0; padding: $gl-padding 0;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $white-dark;
&.oneline-block { &.oneline-block {
line-height: 36px; line-height: 36px;
......
...@@ -162,6 +162,10 @@ ...@@ -162,6 +162,10 @@
} }
} }
.dropdown-menu-full-width {
width: 100%;
}
.dropdown-menu-paging { .dropdown-menu-paging {
.dropdown-page-two, .dropdown-page-two,
.dropdown-menu-back { .dropdown-menu-back {
......
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
.file-holder { .file-holder {
border: 1px solid $border-color; border: 1px solid $border-color;
&.file-holder-no-border {
border: 0;
}
&.readme-holder { &.readme-holder {
margin: $gl-padding-top 0; margin: $gl-padding-top 0;
} }
...@@ -23,8 +27,17 @@ ...@@ -23,8 +27,17 @@
word-wrap: break-word; word-wrap: break-word;
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
&.file-title-clear {
padding-left: 0;
padding-right: 0;
background-color: transparent;
.file-actions {
right: 0;
}
}
.file-actions { .file-actions {
float: right;
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 15px; right: 15px;
......
...@@ -48,10 +48,6 @@ ...@@ -48,10 +48,6 @@
display: block; display: block;
} }
.project-home-desc {
font-size: 21px;
}
.project-repo-buttons, .project-repo-buttons,
.git-clone-holder { .git-clone-holder {
display: none; display: none;
......
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
} }
input { input {
height: 34px; height: 35px;
display: inline-block; display: inline-block;
position: relative; position: relative;
top: 2px; top: 2px;
...@@ -196,7 +196,7 @@ ...@@ -196,7 +196,7 @@
position: fixed; position: fixed;
top: $header-height; top: $header-height;
width: 100%; width: 100%;
z-index: 1; z-index: 11;
background: $background-color; background: $background-color;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
transition-duration: .3s; transition-duration: .3s;
...@@ -238,6 +238,10 @@ ...@@ -238,6 +238,10 @@
@media (max-width: $screen-xs-min) { @media (max-width: $screen-xs-min) {
margin-left: 0; margin-left: 0;
} }
li.active {
font-weight: bold;
}
} }
} }
...@@ -246,6 +250,11 @@ ...@@ -246,6 +250,11 @@
height: 51px; height: 51px;
white-space: nowrap; white-space: nowrap;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
li { li {
...@@ -279,4 +288,8 @@ ...@@ -279,4 +288,8 @@
margin-top: 96px; margin-top: 96px;
} }
} }
.right-sidebar {
top: ($header-height * 2) + 2;
}
} }
...@@ -119,8 +119,8 @@ $border-white-light: #f1f2f4; ...@@ -119,8 +119,8 @@ $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2; $border-white-normal: #d6dae2;
$border-white-dark: #c6cacf; $border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06); $border-gray-light: #dcdcdc;
$border-gray-normal: rgba(0, 0, 0, 0.10);; $border-gray-normal: rgba(0, 0, 0, 0.10);
$border-gray-dark: #c6cacf; $border-gray-dark: #c6cacf;
$border-green-light: #2faa60; $border-green-light: #2faa60;
......
...@@ -40,11 +40,6 @@ ...@@ -40,11 +40,6 @@
} }
} }
.issue-search-form {
margin: 0;
height: 24px;
}
form.edit-issue { form.edit-issue {
margin: 0; margin: 0;
} }
...@@ -96,8 +91,3 @@ form.edit-issue { ...@@ -96,8 +91,3 @@ form.edit-issue {
.issue-form .select2-container { .issue-form .select2-container {
width: 250px !important; width: 250px !important;
} }
.issue-closed-by-widget {
color: $gl-text-color;
margin-left: 52px;
}
...@@ -134,14 +134,6 @@ ...@@ -134,14 +134,6 @@
} }
} }
.change-username-title {
color: $gl-warning;
}
.remove-account-title {
color: $gl-danger;
}
.provider-btn-group { .provider-btn-group {
display: inline-block; display: inline-block;
margin-right: 10px; margin-right: 10px;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
margin-bottom: 0; margin-bottom: 0;
} }
.new_project, .new_project,
.edit_project { .edit-project {
fieldset.features { fieldset.features {
.control-label { .control-label {
font-weight: normal; font-weight: normal;
...@@ -26,8 +26,13 @@ ...@@ -26,8 +26,13 @@
} }
.project-home-panel { .project-home-panel {
padding-bottom: 40px; background: $white-light;
border-bottom: 1px solid $border-color; text-align: left;
padding: 24px 0;
.container-fluid {
position: relative;
}
.cover-controls { .cover-controls {
.project-settings-dropdown { .project-settings-dropdown {
...@@ -43,21 +48,55 @@ ...@@ -43,21 +48,55 @@
} }
} }
.project-identicon-holder { .cover-title {
margin-bottom: 16px; margin-bottom: 0;
}
.avatar, .identicon { .project-image-container {
margin: 0 auto; @include make-sm-column(1);
float: none; max-width: 86px;
min-width: 86px;
padding-right: 0;
margin: 11px 0;
@media (max-width: $screen-md-max) {
padding-left: 0;
margin: 0 0 10px;
max-width: none;
min-width: none;
.avatar.s70 {
margin: auto;
}
}
}
.project-info {
@include make-sm-column(10);
h1 {
font-size: 24px;
font-weight: normal;
margin: 0;
}
.project-home-desc {
p {
margin: 0;
}
}
} }
.identicon { .identicon {
float: left;
@include border-radius(50%); @include border-radius(50%);
} }
.avatar {
float: none;
} }
.notifications-btn { .notifications-btn {
margin-top: -28px;
.fa-bell { .fa-bell {
margin-right: 6px; margin-right: 6px;
...@@ -69,28 +108,45 @@ ...@@ -69,28 +108,45 @@
} }
.project-repo-buttons { .project-repo-buttons {
margin-top: 20px; font-size: 0;
margin-bottom: 0;
.count-buttons { .btn {
display: block; @include btn-gray;
margin-bottom: 20px; padding: 3px 10px;
text-transform: none;
background-color: $background-color;
.fa {
color: $layout-link-gray;
} }
.clone-row { .fa-caret-down {
.split-repo-buttons, margin-left: 3px;
.project-clone-holder { }
display: inline-block;
} }
.split-repo-buttons { .btn-group:not(:first-child):not(:last-child) > .btn {
margin: 0 12px; border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
} }
form {
margin-left: 10px;
} }
.btn { .count-buttons {
@include btn-gray; display: inline-block;
text-transform: none; vertical-align: top;
margin-top: 16px;
}
.project-clone-holder {
display: inline-block;
margin-top: 16px;
input {
height: 29px;
}
} }
.count-with-arrow { .count-with-arrow {
...@@ -140,14 +196,14 @@ ...@@ -140,14 +196,14 @@
line-height: 13px; line-height: 13px;
padding: $gl-vert-padding $gl-padding; padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px; letter-spacing: .4px;
padding: 10px 14px; padding: 7px 14px;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
touch-action: manipulation; touch-action: manipulation;
cursor: pointer; cursor: pointer;
background-image: none; background-image: none;
white-space: nowrap; white-space: nowrap;
margin: 0 11px 0 4px; margin: 0 10px 0 4px;
a { a {
color: inherit; color: inherit;
...@@ -159,6 +215,30 @@ ...@@ -159,6 +215,30 @@
} }
} }
} }
.project-right-buttons {
position: absolute;
right: 16px;
bottom: 0;
.btn {
padding: 3px 10px;
background-color: $background-color;
}
@media (max-width: 1304px) {
top: 0;
}
}
@media (max-width: $screen-md-max) {
text-align: center;
.project-info,
.project-image-container {
width: 100%;
}
}
} }
.split-one { .split-one {
...@@ -289,11 +369,11 @@ a.deploy-project-label { ...@@ -289,11 +369,11 @@ a.deploy-project-label {
} }
.project-stats { .project-stats {
text-align: center;
margin-top: $gl-padding; margin-top: $gl-padding;
margin-bottom: 0; margin-bottom: 0;
padding-top: 10px; padding: 16px 0;
padding-bottom: 4px; background-color: $white-light;
font-size: 0;
ul.nav { ul.nav {
display: inline-block; display: inline-block;
...@@ -304,12 +384,11 @@ a.deploy-project-label { ...@@ -304,12 +384,11 @@ a.deploy-project-label {
} }
.nav > li > a { .nav > li > a {
@include btn-default;
@include btn-gray;
background-color: transparent; background-color: transparent;
border: 1px solid #f7f8fa; margin-right: 12px;
margin-left: 12px; padding: 0 10px;
font-size: 15px;
color: $notes-light-color;
} }
li { li {
...@@ -329,6 +408,10 @@ a.deploy-project-label { ...@@ -329,6 +408,10 @@ a.deploy-project-label {
background-color: #f0f2f5; background-color: #f0f2f5;
} }
} }
&.row-content-block.second-block {
margin-top: 0;
}
} }
pre.light-well { pre.light-well {
...@@ -446,9 +529,14 @@ pre.light-well { ...@@ -446,9 +529,14 @@ pre.light-well {
border-top: 0; border-top: 0;
.edit-project-readme { .edit-project-readme {
z-index: 100; z-index: 2;
position: relative; position: relative;
} }
.wiki h1 {
border-bottom: none;
padding: 0;
}
} }
.git-clone-holder { .git-clone-holder {
......
...@@ -12,3 +12,11 @@ ...@@ -12,3 +12,11 @@
border: 1px solid $warning-message-border; border: 1px solid $warning-message-border;
border-radius: $border-radius-base; border-radius: $border-radius-base;
} }
.warning-title {
color: $gl-warning;
}
.danger-title {
color: $gl-danger;
}
...@@ -16,19 +16,6 @@ ...@@ -16,19 +16,6 @@
} }
} }
.snippet-box {
@include border-radius(2px);
display: block;
float: left;
padding: 0 $gl-padding;
font-weight: normal;
margin-right: 10px;
font-size: $gl-font-size;
border: 1px solid;
line-height: 32px;
}
.markdown-snippet-copy { .markdown-snippet-copy {
position: fixed; position: fixed;
top: -10px; top: -10px;
...@@ -36,3 +23,34 @@ ...@@ -36,3 +23,34 @@
max-height: 0; max-height: 0;
max-width: 0; max-width: 0;
} }
.file-holder.snippet-file-content {
padding-bottom: $gl-padding;
border-bottom: 1px solid $border-color;
.file-title {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
}
.file-actions {
top: 12px;
}
.file-content {
border-left: 1px solid $border-color;
border-right: 1px solid $border-color;
border-bottom: 1px solid $border-color;
}
}
.snippet-title {
font-size: 24px;
font-weight: normal;
}
.snippet-actions {
@media (min-width: $screen-sm-min) {
float: right;
}
}
...@@ -29,6 +29,17 @@ ...@@ -29,6 +29,17 @@
.todo-item { .todo-item {
.todo-title { .todo-title {
@include str-truncated(calc(100% - 174px)); @include str-truncated(calc(100% - 174px));
overflow: visible;
}
.status-box {
margin: 0;
float: none;
display: inline-block;
font-weight: normal;
padding: 0 5px;
line-height: inherit;
font-size: 14px;
} }
.todo-body { .todo-body {
...@@ -76,12 +87,11 @@ ...@@ -76,12 +87,11 @@
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
.todo-item { .todo-item {
padding-left: $gl-padding;
.todo-title { .todo-title {
white-space: normal; white-space: normal;
overflow: visible; overflow: visible;
max-width: 100%; max-width: 100%;
margin-bottom: 10px;
} }
.avatar { .avatar {
......
...@@ -229,6 +229,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -229,6 +229,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if ci_commit if ci_commit
status = ci_commit.status status = ci_commit.status
coverage = ci_commit.try(:coverage) coverage = ci_commit.try(:coverage)
status ||= "preparing"
else else
ci_service = @merge_request.source_project.ci_service ci_service = @merge_request.source_project.ci_service
status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service
...@@ -238,8 +240,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -238,8 +240,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
end end
status = "preparing" if status.nil?
response = { response = {
title: merge_request.title, title: merge_request.title,
sha: merge_request.last_commit_short_sha, sha: merge_request.last_commit_short_sha,
......
...@@ -250,12 +250,12 @@ class IssuableFinder ...@@ -250,12 +250,12 @@ class IssuableFinder
def by_milestone(items) def by_milestone(items)
if milestones? if milestones?
if filter_by_no_milestone? if filter_by_no_milestone?
items = items.where(milestone_id: [-1, nil]) items = items.left_joins_milestones.where(milestone_id: [-1, nil])
elsif filter_by_upcoming_milestone? elsif filter_by_upcoming_milestone?
upcoming_ids = Milestone.upcoming_ids_by_projects(projects) upcoming_ids = Milestone.upcoming_ids_by_projects(projects)
items = items.joins(:milestone).where(milestone_id: upcoming_ids) items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
else else
items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] }) items = items.with_milestone(params[:milestone_title])
if projects if projects
items = items.where(milestones: { project_id: projects }) items = items.where(milestones: { project_id: projects })
......
...@@ -262,6 +262,8 @@ module ApplicationHelper ...@@ -262,6 +262,8 @@ module ApplicationHelper
assignee_id: params[:assignee_id], assignee_id: params[:assignee_id],
author_id: params[:author_id], author_id: params[:author_id],
sort: params[:sort], sort: params[:sort],
issue_search: params[:issue_search],
label_name: params[:label_name]
} }
options = exist_opts.merge(options) options = exist_opts.merge(options)
...@@ -272,16 +274,11 @@ module ApplicationHelper ...@@ -272,16 +274,11 @@ module ApplicationHelper
end end
end end
path = request.path params = options.compact
path << "?#{options.to_param}"
if add_label params.delete(:label_name) unless add_label
if params[:label_name].present? and params[:label_name].respond_to?('any?')
params[:label_name].each do |label| "#{request.path}?#{params.to_param}"
path << "&label_name[]=#{label}"
end
end
end
path
end end
def outdated_browser? def outdated_browser?
......
...@@ -95,7 +95,9 @@ module TabHelper ...@@ -95,7 +95,9 @@ module TabHelper
end end
def project_tab_class def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project) if controller.controller_path.start_with?('projects')
return 'active'
end
if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name
"active" "active"
......
...@@ -37,6 +37,16 @@ module TodosHelper ...@@ -37,6 +37,16 @@ module TodosHelper
end end
end end
def todo_target_state_pill(todo)
return unless show_todo_state?(todo)
content_tag(:span, nil, class: 'target-status') do
content_tag(:span, nil, class: "status-box status-box-#{todo.target.state.dasherize}") do
todo.target.state.capitalize
end
end
end
def todos_filter_params def todos_filter_params
{ {
state: params[:state], state: params[:state],
...@@ -95,4 +105,10 @@ module TodosHelper ...@@ -95,4 +105,10 @@ module TodosHelper
options_from_collection_for_select(types, 'name', 'title', params[:type]) options_from_collection_for_select(types, 'name', 'title', params[:type])
end end
private
def show_todo_state?(todo)
(todo.target.is_a?(MergeRequest) || todo.target.is_a?(Issue)) && ['closed', 'merged'].include?(todo.target.state)
end
end end
...@@ -31,18 +31,21 @@ module Issuable ...@@ -31,18 +31,21 @@ module Issuable
scope :unassigned, -> { where("assignee_id IS NULL") } scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) } scope :of_projects, ->(ids) { where(project_id: ids) }
scope :of_milestones, ->(ids) { where(milestone_id: ids) } scope :of_milestones, ->(ids) { where(milestone_id: ids) }
scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) }
scope :opened, -> { with_state(:opened, :reopened) } scope :opened, -> { with_state(:opened, :reopened) }
scope :only_opened, -> { with_state(:opened) } scope :only_opened, -> { with_state(:opened) }
scope :only_reopened, -> { with_state(:reopened) } scope :only_reopened, -> { with_state(:reopened) }
scope :closed, -> { with_state(:closed) } scope :closed, -> { with_state(:closed) }
scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') }
scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :left_joins_milestones, -> { joins("LEFT OUTER JOIN milestones ON #{table_name}.milestone_id = milestones.id") }
scope :order_milestone_due_desc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date DESC') }
scope :order_milestone_due_asc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :join_project, -> { joins(:project) } scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) } scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) } scope :non_archived, -> { join_project.where(projects: { archived: false }) }
scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") }
delegate :name, delegate :name,
:email, :email,
......
...@@ -431,7 +431,13 @@ class Project < ActiveRecord::Base ...@@ -431,7 +431,13 @@ class Project < ActiveRecord::Base
def check_limit def check_limit
unless creator.can_create_project? or namespace.kind == 'group' unless creator.can_create_project? or namespace.kind == 'group'
self.errors.add(:limit_reached, "Your project limit is #{creator.projects_limit} projects! Please contact your administrator to increase it") projects_limit = creator.projects_limit
if projects_limit == 0
self.errors.add(:limit_reached, "Personal project creation is not allowed. Please contact your administrator with questions")
else
self.errors.add(:limit_reached, "Your project limit is #{projects_limit} projects! Please contact your administrator to increase it")
end
end end
rescue rescue
self.errors.add(:base, "Can't check your ability to create project") self.errors.add(:base, "Can't check your ability to create project")
......
...@@ -35,7 +35,7 @@ class SlackService ...@@ -35,7 +35,7 @@ class SlackService
private private
def message def message
"#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} second(s)" "#{project_link}: Commit #{commit_link} of #{branch_link} #{ref_type} by #{user_name} #{humanized_status} in #{duration} #{'second'.pluralize(duration)}"
end end
def format(string) def format(string)
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:'' = image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
.todo-title.title .todo-title.title
- unless todo.build_failed? - unless todo.build_failed?
= todo_target_state_pill(todo)
%span.author-name %span.author-name
- if todo.author - if todo.author
= link_to_author(todo) = link_to_author(todo)
......
%h3.page-title Authorize required %h3.page-title Authorization required
%main{:role => "main"} %main{:role => "main"}
%p.h4 %p.h4
Authorize Authorize
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
%td.import-target %td.import-target
= repo["path_with_namespace"] = repo["path_with_namespace"]
%td.import-actions.job-status %td.import-actions.job-status
= button_tag class: "btn js-add-to-import" do = button_tag class: "btn btn-import js-add-to-import" do
Import Import
= icon("spinner spin", class: "loading-icon") = icon("spinner spin", class: "loading-icon")
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
= link_to dashboard_projects_path, title: 'Projects' do = link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
= icon('bookmark fw') = icon('bookmark fw')
%span %span
Projects Projects
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
Todos Todos
%span.count.todos-pending-count= number_with_delimiter(todos_pending_count) %span.count.todos-pending-count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do = nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
= icon('dashboard fw') = icon('dashboard fw')
%span %span
Activity Activity
...@@ -26,13 +26,13 @@ ...@@ -26,13 +26,13 @@
%span %span
Milestones Milestones
= nav_link(path: 'dashboard#issues') do = nav_link(path: 'dashboard#issues') do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
= icon('exclamation-circle fw') = icon('exclamation-circle fw')
%span %span
Issues Issues
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count) %span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do = nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do = link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
= icon('tasks fw') = icon('tasks fw')
%span %span
Merge Requests Merge Requests
......
%ul.nav.nav-sidebar - if current_user
- if @project.group .controls
= nav_link do - access = user_max_access_in_project(current_user.id, @project)
= link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do - can_edit = can?(current_user, :admin_project, @project)
= icon('caret-square-o-left fw') .dropdown.project-settings-dropdown
%span %a.dropdown-new.btn.btn-default#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
Go to group = icon('cog')
- else = icon('caret-down')
= nav_link do %ul.dropdown-menu.dropdown-menu-align-right
= link_to root_path, title: 'Go to dashboard', class: 'back-link' do = render 'layouts/nav/project_settings'
= icon('caret-square-o-left fw') %li.divider
%span - if can_edit
Go to dashboard %li
= link_to edit_project_path(@project) do
%li.separate-item Edit Project
- if access
%li
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave Project
%ul.nav-links
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
= icon('bookmark fw') = icon('bookmark fw')
...@@ -44,7 +50,7 @@ ...@@ -44,7 +50,7 @@
= icon('ship fw') = icon('ship fw')
%span %span
Pipelines Pipelines
%span.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count) %span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
- if project_nav_tab? :builds - if project_nav_tab? :builds
= nav_link(controller: %w(builds)) do = nav_link(controller: %w(builds)) do
...@@ -52,7 +58,7 @@ ...@@ -52,7 +58,7 @@
= icon('cubes fw') = icon('cubes fw')
%span %span
Builds Builds
%span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all)) %span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
- if project_nav_tab? :container_registry - if project_nav_tab? :container_registry
= nav_link(controller: %w(container_registry)) do = nav_link(controller: %w(container_registry)) do
...@@ -82,7 +88,7 @@ ...@@ -82,7 +88,7 @@
%span %span
Issues Issues
- if @project.default_issues_tracker? - if @project.default_issues_tracker?
%span.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count) %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? :merge_requests
= nav_link(controller: :merge_requests) do = nav_link(controller: :merge_requests) do
...@@ -90,14 +96,7 @@ ...@@ -90,14 +96,7 @@
= icon('tasks fw') = icon('tasks fw')
%span %span
Merge Requests Merge Requests
%span.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count) %span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
- if project_nav_tab? :team
= nav_link(controller: [:project_members, :teams]) do
= link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
= icon('users fw')
%span
Members
- if project_nav_tab? :labels - if project_nav_tab? :labels
= nav_link(controller: :labels) do = nav_link(controller: :labels) do
...@@ -113,13 +112,6 @@ ...@@ -113,13 +112,6 @@
%span %span
Wiki Wiki
- if project_nav_tab? :forks
= nav_link(controller: :forks, action: :index) do
= link_to namespace_project_forks_path(@project.namespace, @project), title: 'Forks' do
= icon('code-fork fw')
%span
Forks
- if project_nav_tab? :snippets - if project_nav_tab? :snippets
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
...@@ -127,13 +119,6 @@ ...@@ -127,13 +119,6 @@
%span %span
Snippets Snippets
- if project_nav_tab? :settings
= nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
= link_to edit_project_path(@project), title: 'Settings' do
= icon('cogs fw')
%span
Settings
-# Global shortcut to network page for compatibility -# Global shortcut to network page for compatibility
- if project_nav_tab? :network - if project_nav_tab? :network
%li.hidden %li.hidden
......
%ul.nav.nav-sidebar - if project_nav_tab? :team
= nav_link do = nav_link(controller: [:project_members, :teams]) do
= link_to project_path(@project), title: 'Go to project', class: 'back-link' do = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
= icon('caret-square-o-left fw')
%span %span
Go to project Members
%li.separate-item - if @project.allowed_to_share_with_group?
%ul.sidebar-subnav
= nav_link(path: 'projects#edit') do
= link_to edit_project_path(@project), title: 'Project Settings' do
= icon('pencil-square-o fw')
%span
Project Settings
- if @project.allowed_to_share_with_group?
= nav_link(controller: :group_links) do = nav_link(controller: :group_links) do
= link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do = link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
= icon('share-square-o fw')
%span %span
Groups Groups
= nav_link(controller: :deploy_keys) do = nav_link(controller: :deploy_keys) do
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
= icon('key fw')
%span %span
Deploy Keys Deploy Keys
= nav_link(controller: :hooks) do = nav_link(controller: :hooks) do
= link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
= icon('link fw')
%span %span
Webhooks Webhooks
= nav_link(controller: :services) do = nav_link(controller: :services) do
= link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
= icon('cogs fw')
%span %span
Services Services
= nav_link(controller: :protected_branches) do = nav_link(controller: :protected_branches) do
= link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
= icon('lock fw')
%span %span
Protected Branches Protected Branches
- if @project.builds_enabled? - if @project.builds_enabled?
= nav_link(controller: :runners) do = nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
= icon('cog fw')
%span %span
Runners Runners
= nav_link(controller: :variables) do = nav_link(controller: :variables) do
= link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do = link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
= icon('code fw')
%span %span
Variables Variables
= nav_link(controller: :triggers) do = nav_link(controller: :triggers) do
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
= icon('retweet fw')
%span %span
Triggers Triggers
= nav_link(controller: :badges) do = nav_link(controller: :badges) do
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do = link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
= icon('star-half-empty fw')
%span %span
Badges Badges
- page_title @project.name_with_namespace - page_title @project.name_with_namespace
- page_description @project.description unless page_description - page_description @project.description unless page_description
- header_title project_title(@project) unless header_title - header_title project_title(@project) unless header_title
- sidebar "project" unless sidebar - nav "project"
- content_for :scripts_body_top do - content_for :scripts_body_top do
- project = @target_project || @project - project = @target_project || @project
......
- page_title "Settings" - page_title "Settings"
- header_title project_title(@project, "Settings", edit_project_path(@project)) - nav "project"
- sidebar "project_settings"
= render template: "layouts/project" = render template: "layouts/project"
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
- if current_user.can_change_username? - if current_user.can_change_username?
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0.change-username-title %h4.prepend-top-0.warning-title
Change username Change username
%p %p
Changing your username will change path to all personal projects! Changing your username will change path to all personal projects!
...@@ -94,7 +94,7 @@ ...@@ -94,7 +94,7 @@
- if signup_enabled? - if signup_enabled?
.row.prepend-top-default .row.prepend-top-default
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0.remove-account-title %h4.prepend-top-0.danger-title
Remove account Remove account
.col-lg-9 .col-lg-9
- if @user.can_be_removed? - if @user.can_be_removed?
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%h4.prepend-top-0 %h4.prepend-top-0
Application theme Application theme
%p %p
This setting allows you to customize the appearance of the site, ex. sidebar. This setting allows you to customize the appearance of the site, e.g. the sidebar.
.col-lg-9.application-theme .col-lg-9.application-theme
- Gitlab::Themes.each do |theme| - Gitlab::Themes.each do |theme|
= label_tag do = label_tag do
......
%fieldset.builds-feature %fieldset.builds-feature
%legend %h5.prepend-top-0
Builds: Builds
- unless @repository.gitlab_ci_yml - unless @repository.gitlab_ci_yml
.form-group .form-group
.col-sm-offset-2.col-sm-10
%p Builds need to be configured before you can begin using Continuous Integration. %p Builds need to be configured before you can begin using Continuous Integration.
= link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info' = link_to 'Get started with Builds', help_page_path('ci/quick_start', 'README'), class: 'btn btn-info'
%hr
.form-group .form-group
.col-sm-offset-2.col-sm-10
%p Get recent application code using the following command: %p Get recent application code using the following command:
.radio .radio
= f.label :build_allow_git_fetch_false do = f.label :build_allow_git_fetch_false do
...@@ -26,13 +21,11 @@ ...@@ -26,13 +21,11 @@
%span.descr Faster %span.descr Faster
.form-group .form-group
= f.label :build_timeout_in_minutes, 'Timeout', class: 'control-label' = f.label :build_timeout_in_minutes, 'Timeout', class: 'label-light'
.col-sm-10
= f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0' = f.number_field :build_timeout_in_minutes, class: 'form-control', min: '0'
%p.help-block per build in minutes %p.help-block per build in minutes
.form-group .form-group
= f.label :build_coverage_regex, "Test coverage parsing", class: 'control-label' = f.label :build_coverage_regex, "Test coverage parsing", class: 'label-light'
.col-sm-10
.input-group .input-group
%span.input-group-addon / %span.input-group-addon /
= f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered' = f.text_field :build_coverage_regex, class: 'form-control', placeholder: '\(\d+.\d+\%\) covered'
...@@ -60,15 +53,13 @@ ...@@ -60,15 +53,13 @@
%code ^Statements\s*:\s*([^%]+) %code ^Statements\s*:\s*([^%]+)
.form-group .form-group
.col-sm-offset-2.col-sm-10
.checkbox .checkbox
= f.label :public_builds do = f.label :public_builds do
= f.check_box :public_builds = f.check_box :public_builds
%strong Public builds %strong Public builds
.help-block Allow everyone to access builds for Public and Internal projects .help-block Allow everyone to access builds for Public and Internal projects
.form-group .form-group.append-bottom-0
= f.label :runners_token, "Runners token", class: 'control-label' = f.label :runners_token, "Runners token", class: 'label-light'
.col-sm-10
= f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89' = f.text_field :runners_token, class: "form-control", placeholder: 'xEeFCaDAB89'
%p.help-block The secure token used to checkout project. %p.help-block The secure token used to checkout project.
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)} .project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder .container-fluid.container-limited
= project_icon(@project, alt: '', class: 'project-avatar avatar s90') .row
.project-image-container
= project_icon(@project, alt: '', class: 'project-avatar avatar s70')
.project-info
.cover-title.project-home-desc .cover-title.project-home-desc
%h1 %h1
= @project.name = @project.name
...@@ -18,42 +21,17 @@ ...@@ -18,42 +21,17 @@
= link_to project_path(forked_from_project) do = link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name) = forked_from_project.namespace.try(:name)
.cover-controls
- if current_user
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do
= icon('rss')
- access = user_max_access_in_project(current_user.id, @project)
- can_edit = can?(current_user, :admin_project, @project)
- if access || can_edit
%span.dropdown.project-settings-dropdown
%a.dropdown-new.btn.btn-gray#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
= icon('cog')
= icon('angle-down')
%ul.dropdown-menu.dropdown-menu-right
- if can_edit
%li
= link_to edit_project_path(@project) do
Edit Project
- if access
%li
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave Project
.project-repo-buttons .project-repo-buttons
.split-one.count-buttons .count-buttons
= render 'projects/buttons/star' = render 'projects/buttons/star'
= render 'projects/buttons/fork' = render 'projects/buttons/fork'
.clone-row
.project-clone-holder .project-clone-holder
= render "shared/clone_panel" = render "shared/clone_panel"
.split-repo-buttons .project-repo-buttons.btn-group.project-right-buttons
.btn-group.pull-left
= render "projects/buttons/download" = render "projects/buttons/download"
= render 'projects/buttons/dropdown' = render 'projects/buttons/dropdown'
= render 'projects/buttons/notifications' = render 'projects/buttons/notifications'
:javascript :javascript
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
.btn-group .btn-group
%a.btn.dropdown-toggle{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-align-right.project-home-dropdown
- can_create_issue = can?(current_user, :create_issue, @project) - can_create_issue = can?(current_user, :create_issue, @project)
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- can_create_snippet = can?(current_user, :create_snippet, @project) - can_create_snippet = can?(current_user, :create_snippet, @project)
......
- if @notification_setting - if @notification_setting
= form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f| = form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f|
= f.hidden_field :level = f.hidden_field :level
%span.dropdown .dropdown
%a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"} %a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"}
= icon('bell') = icon('bell')
= notification_title(@notification_setting.level) = notification_title(@notification_setting.level)
= icon('angle-down') = icon('caret-down')
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown %ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown
- NotificationSetting.levels.each do |level| - NotificationSetting.levels.each do |level|
= notification_list_item(level.first, @notification_setting) = notification_list_item(level.first, @notification_setting)
This diff is collapsed.
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
%td %td
= generic_commit_status.name = generic_commit_status.name
.pull-right %td
- if generic_commit_status.tags.any? - if generic_commit_status.tags.any?
- generic_commit_status.tags.each do |tag| - generic_commit_status.tags.each do |tag|
%span.label.label-primary %span.label.label-primary
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
.header.clearfix .header.clearfix
%h3#date_header.page-title %h3#date_header.page-title
%p.light %p.light
Commits to #{@ref}, excluding merge commits. Limited by 6,000 commits Commits to #{@ref}, excluding merge commits. Limited to 6,000 commits.
%input#brush_change{:type => "hidden"} %input#brush_change{:type => "hidden"}
.graphs .graphs
#contributors-master #contributors-master
......
...@@ -24,5 +24,8 @@ ...@@ -24,5 +24,8 @@
MERGED MERGED
- elsif merge_request.closed? - elsif merge_request.closed?
CLOSED CLOSED
%li
= render partial: 'projects/issues/closed_by_box', locals: {merge_request_count: @merge_requests.count}
- if @closed_by_merge_requests.present? - 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}
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
- else - else
.nothing-here-block .nothing-here-block
- if can? current_user, :admin_label, @project - if can? current_user, :admin_label, @project
Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}.
- else - else
No labels created No labels created
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
Install GitLab Runner software. Install GitLab Runner software.
Checkout the #{link_to 'GitLab Runner section', 'https://about.gitlab.com/gitlab-ci/#gitlab-runner', target: '_blank'} to install it Checkout the #{link_to 'GitLab Runner section', 'https://about.gitlab.com/gitlab-ci/#gitlab-runner', target: '_blank'} to install it
%li %li
Specify following URL during runner setup: Specify the following URL during runner setup:
%code #{ci_root_url(only_path: false)} %code #{ci_root_url(only_path: false)}
%li %li
Use the following registration token during setup: Use the following registration token during setup:
......
...@@ -13,20 +13,20 @@ ...@@ -13,20 +13,20 @@
= render "home_panel" = render "home_panel"
.project-stats.row-content-block.second-block .project-stats.row-content-block.second-block
.container-fluid.container-limited
%ul.nav %ul.nav
%li
= link_to project_files_path(@project) do
Files (#{repository_size})
%li %li
= link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do = link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
= pluralize(number_with_delimiter(@project.commit_count), 'commit') #{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
%li %li
= link_to namespace_project_branches_path(@project.namespace, @project) do = link_to namespace_project_branches_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.branch_names.count), 'branch') #{'Branch'.pluralize(@repository.branch_names.count)} (#{number_with_delimiter(@repository.branch_names.count)})
%li %li
= link_to namespace_project_tags_path(@project.namespace, @project) do = link_to namespace_project_tags_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.tag_names.count), 'tag') #{'Tag'.pluralize(@repository.tag_names.count)} (#{number_with_delimiter(@repository.tag_names.count)})
%li
= link_to project_files_path(@project) do
= repository_size
- if default_project_view != 'readme' && @repository.readme - if default_project_view != 'readme' && @repository.readme
%li %li
......
= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do .hidden-xs
= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped btn-create new-snippet-link', title: "New Snippet" do
= icon('plus') = icon('plus')
New Snippet New Snippet
- if can?(current_user, :admin_project_snippet, @snippet) - if can?(current_user, :update_project_snippet, @snippet)
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do
= icon('trash-o')
Delete
- if can?(current_user, :update_project_snippet, @snippet)
= link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
= icon('pencil-square-o')
Edit Edit
- if can?(current_user, :update_project_snippet, @snippet)
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
Delete
.visible-xs-block.dropdown
%button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
Options
%span.caret
.dropdown-menu.dropdown-menu-full-width
%ul
%li
= link_to new_namespace_project_snippet_path(@project.namespace, @project), title: "New Snippet" do
New Snippet
- if can?(current_user, :update_project_snippet, @snippet)
%li
= link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet) do
Edit
- if can?(current_user, :update_project_snippet, @snippet)
%li
= link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
Delete
...@@ -4,15 +4,13 @@ ...@@ -4,15 +4,13 @@
.snippet-holder .snippet-holder
= render 'shared/snippets/header' = render 'shared/snippets/header'
%article.file-holder %article.file-holder.file-holder-no-border.snippet-file-content
.file-title .file-title.file-title-clear
= blob_icon 0, @snippet.file_name = blob_icon 0, @snippet.file_name
%strong
= @snippet.file_name = @snippet.file_name
.file-actions.hidden-xs .file-actions.hidden-xs
= clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']")
= link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank" = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank"
= render 'shared/snippets/blob' = render 'shared/snippets/blob'
%div#notes= render "projects/notes/notes_with_form" %div#notes= render "projects/notes/notes_with_form"
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%h4.prepend-top-0 %h4.prepend-top-0
= page_title = page_title
%p %p
Triggers can be used to force a rebuild of a specific branch or tag with an API call. Triggers can force a specific branch or tag to rebuild with an API call.
.col-lg-9 .col-lg-9
%h5.prepend-top-0 %h5.prepend-top-0
Your triggers Your triggers
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
= render partial: 'trigger', collection: @triggers, as: :trigger = render partial: 'trigger', collection: @triggers, as: :trigger
- else - else
%p.settings-message.text-center.append-bottom-default %p.settings-message.text-center.append-bottom-default
There are no triggers to use, add one by the button below. No triggers have been created yet. Add one using the button below.
= form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f| = form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f|
= f.submit "Add Trigger", class: 'btn btn-success' = f.submit "Add Trigger", class: 'btn btn-success'
...@@ -28,8 +28,7 @@ ...@@ -28,8 +28,7 @@
Use CURL Use CURL
%p.light %p.light
Copy the token above and set your branch or tag name. This is the reference that will be rebuild. Copy the token above, set your branch or tag name, and that reference will be rebuilt.
%pre %pre
:plain :plain
...@@ -41,10 +40,10 @@ ...@@ -41,10 +40,10 @@
Use .gitlab-ci.yml Use .gitlab-ci.yml
%p.light %p.light
Copy the snippet to In the
%i .gitlab-ci.yml %code .gitlab-ci.yml
of dependent project. of the dependent project, include the following snippet.
At the end of your build it will trigger this project to rebuilt. The project will rebuild at the end of the build.
%pre %pre
:plain :plain
...@@ -57,9 +56,8 @@ ...@@ -57,9 +56,8 @@
%p.light %p.light
Add Add
%strong variables[VARIABLE]=VALUE %code variables[VARIABLE]=VALUE
to API request. to an API request. Variable values can be used to distinguish between triggered builds and normal builds.
The value of variable could then be used to distinguish triggered build from normal one.
%pre.append-bottom-0 %pre.append-bottom-0
:plain :plain
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
%a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'} %a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
%span %span
= default_clone_protocol.upcase = default_clone_protocol.upcase
= icon('angle-down') = icon('caret-down')
%ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown %ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
%li %li
= ssh_clone_button(project) = ssh_clone_button(project)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
- else - else
= sort_title_recently_created = sort_title_recently_created
%b.caret %b.caret
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort
%li %li
= link_to page_filter_path(sort: sort_value_recently_created) do = link_to page_filter_path(sort: sort_value_recently_created) do
= sort_title_recently_created = sort_title_recently_created
......
.issues-filters .issues-filters
.issues-details-filters.row-content-block.second-block .issues-details-filters.row-content-block.second-block
= form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :issue_search]), method: :get, class: 'filter-form js-filter-form' do
- if params[:issue_search].present?
= hidden_field_tag :issue_search, params[:issue_search]
- if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project) - if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project)
.check-all-holder .check-all-holder
= check_box_tag "check_all_issues", nil, false, = check_box_tag "check_all_issues", nil, false,
......
= form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do = form_tag(path, method: :get, id: "issue_search_form", class: 'issue-search-form') do
= search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false } = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input input-short', spellcheck: false }
= hidden_field_tag :state, params['state']
= hidden_field_tag :scope, params['scope']
= hidden_field_tag :assignee_id, params['assignee_id']
= hidden_field_tag :author_id, params['author_id']
= hidden_field_tag :milestone_id, params['milestone_id']
= hidden_field_tag :label_id, params['label_id']
.detail-page-header .detail-page-header.clearfix
.snippet-box.has-tooltip{class: visibility_level_color(@snippet.visibility_level), title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: 'body' }} .snippet-box.has-tooltip.inline.append-right-5{ title: snippet_visibility_level_description(@snippet.visibility_level, @snippet), data: { container: "body" } }
= visibility_level_icon(@snippet.visibility_level, fw: false) %span.sr-only
= visibility_level_label(@snippet.visibility_level) = visibility_level_label(@snippet.visibility_level)
%span.identifier = visibility_level_icon(@snippet.visibility_level, fw: false)
%strong.item-title
Snippet ##{@snippet.id} Snippet ##{@snippet.id}
%span.creator %span.creator
&middot; created by #{link_to_member(@project, @snippet.author, size: 24)} created by #{link_to_member(@project, @snippet.author, size: 24, author_class: "author item-title")}
&middot;
= time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago') = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
- if @snippet.updated_at != @snippet.created_at - if @snippet.updated_at != @snippet.created_at
%span %span
&middot;
= icon('edit', title: 'edited') = icon('edit', title: 'edited')
= time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago') = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
.pull-right .snippet-actions
- if @snippet.project_id? - if @snippet.project_id?
= render "projects/snippets/actions" = render "projects/snippets/actions"
- else - else
= render "snippets/actions" = render "snippets/actions"
.detail-page-description.row-content-block.second-block .content-block.second-block
%h2.title %h2.snippet-title.prepend-top-0.append-bottom-0
= markdown escape_once(@snippet.title), pipeline: :single_line = markdown escape_once(@snippet.title), pipeline: :single_line
= link_to new_snippet_path, class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do .hidden-xs
= link_to new_snippet_path, class: "btn btn-grouped btn-create new-snippet-link", title: "New Snippet" do
= icon('plus') = icon('plus')
New Snippet New Snippet
- if can?(current_user, :update_personal_snippet, @snippet) - if can?(current_user, :update_personal_snippet, @snippet)
= link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
= icon('pencil-square-o')
Edit Edit
- if can?(current_user, :admin_personal_snippet, @snippet) - if can?(current_user, :admin_personal_snippet, @snippet)
= link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-warning", title: 'Delete Snippet' do
= icon('trash-o') Delete
.visible-xs-block.dropdown
%button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
Options
%span.caret
.dropdown-menu.dropdown-menu-full-width
%ul
%li
= link_to new_snippet_path, title: "New Snippet" do
New Snippet
- if can?(current_user, :update_personal_snippet, @snippet)
%li
= link_to edit_snippet_path(@snippet) do
Edit
- if can?(current_user, :admin_personal_snippet, @snippet)
%li
= link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
Delete Delete
...@@ -3,10 +3,9 @@ ...@@ -3,10 +3,9 @@
.snippet-holder .snippet-holder
= render 'shared/snippets/header' = render 'shared/snippets/header'
%article.file-holder %article.file-holder.file-holder-no-border.snippet-file-content
.file-title .file-title.file-title-clear
= blob_icon 0, @snippet.file_name = blob_icon 0, @snippet.file_name
%strong
= @snippet.file_name = @snippet.file_name
.file-actions.hidden-xs .file-actions.hidden-xs
= clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']") = clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{@snippet.id}']")
......
...@@ -26,7 +26,7 @@ that runs Redis. ...@@ -26,7 +26,7 @@ that runs Redis.
```ruby ```ruby
external_url 'https://gitlab.example.com' external_url 'https://gitlab.example.com'
# Disable all components except PostgreSQL # Disable all components except Redis
redis['enable'] = true redis['enable'] = true
bootstrap['enable'] = false bootstrap['enable'] = false
nginx['enable'] = false nginx['enable'] = false
......
...@@ -65,7 +65,7 @@ the command line via `bundle exec teaspoon`, or via a web browser at ...@@ -65,7 +65,7 @@ the command line via `bundle exec teaspoon`, or via a web browser at
- Use `context` to test branching logic. - Use `context` to test branching logic.
- Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)). - Don't `describe` symbols (see [Gotchas](gotchas.md#dont-describe-symbols)).
- Don't supply the `:each` argument to hooks since it's the default. - Don't supply the `:each` argument to hooks since it's the default.
- Prefer `not_to` to `to_not`. - Prefer `not_to` to `to_not` (_this is enforced by Rubocop_).
- Try to match the ordering of tests to the ordering within the class. - Try to match the ordering of tests to the ordering within the class.
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines - Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
to separate phases. to separate phases.
......
...@@ -6,3 +6,31 @@ We created a page inside GitLab where you can check commonly used html and css e ...@@ -6,3 +6,31 @@ We created a page inside GitLab where you can check commonly used html and css e
When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
you can use during GitLab development. you can use during GitLab development.
## Design repository
All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
repository and maintained by GitLab UX designers.
## Navigation
GitLab's layout contains 2 sections: the left sidebar and the content. The left sidebar contains a static navigation menu.
This menu will be visible regardless of what page you visit. The left sidebar also contains the GitLab logo
and the current user's profile picture. The content section contains a header and the content itself.
The header describes the current GitLab page and what navigation is
available to user in this area. Depending on the area (project, group, profile setting) the header name and navigation may change. For example when user visits one of the
project pages the header will contain a project name and navigation for that project. When the user visits a group page it will contain a group name and navigation related to this group.
### Adding new tab to header navigation
We try to keep the amount of tabs in the header navigation between 5 and 10 so that it fits on a typical laptop screen. We also try not to confuse the user with too many options. Ideally each
tab should represent separate functionality. Everything related to the issue
tracker should be under the 'Issues' tab while everything related to the wiki should
be under 'Wiki' tab and so on and so forth.
## Mobile screen size
We want GitLab to work well on small mobile screens as well. Size limitations make it is impossible to fit everything on a mobile screen. In this case it is OK to hide
part of the UI for smaller resolutions in favor of a better user experience.
However core functionality like browsing files, creating issues, writing comments, should
be available on all resolutions.
\ No newline at end of file
...@@ -271,7 +271,7 @@ sudo usermod -aG redis git ...@@ -271,7 +271,7 @@ sudo usermod -aG redis git
# Clone GitLab repository # Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-8-stable gitlab sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 8-8-stable gitlab
**Note:** You can change `8-7-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! **Note:** You can change `8-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It ### Configure It
......
...@@ -11,9 +11,9 @@ To enable the Google OAuth2 OmniAuth provider you must register your application ...@@ -11,9 +11,9 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
- Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one. - Project ID: Must be unique to all Google Developer registered applications. Google provides a randomly generated Project ID by default. You can use the randomly generated ID or choose a new one.
1. Refresh the page. You should now see your new project in the list. Click on the project. 1. Refresh the page. You should now see your new project in the list. Click on the project.
1. Select "APIs & auth" in the left menu. 1. Select the "Google APIs" tab in the Overview.
1. Select "APIs" in the submenu. 1. Select and enable the following Google APIs - listed under "Popular APIs"
- Enable `Contacts API` - Enable `Contacts API`
- Enable `Google+ API` - Enable `Google+ API`
......
...@@ -11,7 +11,7 @@ and access the cache. This endpoint can be provided to uptime monitoring service ...@@ -11,7 +11,7 @@ and access the cache. This endpoint can be provided to uptime monitoring service
## Access Token ## Access Token
An access token needs to be provided while accessing the health check endpoint. The current An access token needs to be provided while accessing the health check endpoint. The current
accepted token can be found on the `admin/heath_check` page of your GitLab instance. accepted token can be found on the `admin/health_check` page of your GitLab instance.
![access token](img/health_check_token.png) ![access token](img/health_check_token.png)
......
...@@ -30,11 +30,6 @@ Feature: Project Active Tab ...@@ -30,11 +30,6 @@ Feature: Project Active Tab
Then the active main tab should be Merge Requests Then the active main tab should be Merge Requests
And no other main tabs should be active And no other main tabs should be active
Scenario: On Project Members
Given I visit my project's members page
Then the active main tab should be Members
And no other main tabs should be active
Scenario: On Project Wiki Scenario: On Project Wiki
Given I visit my project's wiki page Given I visit my project's wiki page
Then the active main tab should be Wiki Then the active main tab should be Wiki
...@@ -49,13 +44,6 @@ Feature: Project Active Tab ...@@ -49,13 +44,6 @@ Feature: Project Active Tab
# Sub Tabs: Settings # Sub Tabs: Settings
Scenario: On Project Settings/Edit
Given I visit my project's settings page
And I click the "Edit" tab
Then the active sub nav should be Edit
And no other sub navs should be active
And the active main tab should be Settings
Scenario: On Project Settings/Hooks Scenario: On Project Settings/Hooks
Given I visit my project's settings page Given I visit my project's settings page
And I click the "Hooks" tab And I click the "Hooks" tab
...@@ -70,6 +58,12 @@ Feature: Project Active Tab ...@@ -70,6 +58,12 @@ Feature: Project Active Tab
And no other sub navs should be active And no other sub navs should be active
And the active main tab should be Settings And the active main tab should be Settings
Scenario: On Project Members
Given I visit my project's members page
Then the active sub nav should be Members
And no other sub navs should be active
And the active main tab should be Settings
# Sub Tabs: Commits # Sub Tabs: Commits
Scenario: On Project Commits/Commits Scenario: On Project Commits/Commits
......
...@@ -18,15 +18,6 @@ Feature: Project ...@@ -18,15 +18,6 @@ Feature: Project
Then I should see the default project avatar Then I should see the default project avatar
And I should not see the "Remove avatar" button And I should not see the "Remove avatar" button
Scenario: I should have back to group button
And project "Shop" belongs to group
And I visit project "Shop" page
Then I should see back to group button
Scenario: I should have back to group button
And I visit project "Shop" page
Then I should see back to dashboard button
Scenario: I should have readme on page Scenario: I should have readme on page
And I visit project "Shop" page And I visit project "Shop" page
Then I should see project "Shop" README Then I should see project "Shop" README
......
class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedActiveTab include SharedSidebarActiveTab
step 'the active main tab should be Home' do step 'the active main tab should be Home' do
ensure_active_main_tab('Overview') ensure_active_main_tab('Overview')
...@@ -34,4 +34,12 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps ...@@ -34,4 +34,12 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Messages' do step 'the active main tab should be Messages' do
ensure_active_main_tab('Messages') ensure_active_main_tab('Messages')
end end
step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
end
def ensure_active_main_tab(content)
expect(find('.nav-sidebar > li.active')).to have_content(content)
end
end end
...@@ -158,7 +158,7 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps ...@@ -158,7 +158,7 @@ class Spinach::Features::AdminUsers < Spinach::FeatureSteps
step 'I should not see twitter details' do step 'I should not see twitter details' do
expect(page).to have_content 'Pete' expect(page).to have_content 'Pete'
expect(page).to_not have_content 'twitter' expect(page).not_to have_content 'twitter'
end end
step 'click on ssh keys tab' do step 'click on ssh keys tab' do
......
class Spinach::Features::DashboardActiveTab < Spinach::FeatureSteps class Spinach::Features::DashboardActiveTab < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedActiveTab include SharedSidebarActiveTab
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
end end
...@@ -2,5 +2,6 @@ class Spinach::Features::DashboardShortcuts < Spinach::FeatureSteps ...@@ -2,5 +2,6 @@ class Spinach::Features::DashboardShortcuts < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedPaths include SharedPaths
include SharedProject include SharedProject
include SharedActiveTab include SharedSidebarActiveTab
include SharedShortcuts
end end
...@@ -106,7 +106,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps ...@@ -106,7 +106,7 @@ class Spinach::Features::DashboardTodos < Spinach::FeatureSteps
if pending if pending
expect(page).to have_link 'Done' expect(page).to have_link 'Done'
else else
expect(page).to_not have_link 'Done' expect(page).not_to have_link 'Done'
end end
end end
end end
......
...@@ -22,8 +22,4 @@ class Spinach::Features::ProfileActiveTab < Spinach::FeatureSteps ...@@ -22,8 +22,4 @@ class Spinach::Features::ProfileActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Audit Log' do step 'the active main tab should be Audit Log' do
ensure_active_main_tab('Audit Log') ensure_active_main_tab('Audit Log')
end end
def ensure_active_main_tab(content)
expect(find('.layout-nav li.active')).to have_content(content)
end
end end
...@@ -16,12 +16,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -16,12 +16,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end end
step 'I click the "Snippets" tab' do step 'I click the "Snippets" tab' do
page.within('.layout-nav') do
click_link('Snippets') click_link('Snippets')
end end
end
step 'I click the "Edit" tab' do step 'I click the "Edit Project"' do
page.within '.sidebar-subnav' do page.within '.layout-nav .controls' do
click_link('Project Settings') click_link('Edit Project')
end end
end end
...@@ -33,14 +35,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -33,14 +35,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
click_link('Deploy Keys') click_link('Deploy Keys')
end end
step 'the active sub nav should be Team' do step 'the active sub nav should be Members' do
ensure_active_sub_nav('Members') ensure_active_sub_nav('Members')
end end
step 'the active sub nav should be Edit' do
ensure_active_sub_nav('Project')
end
step 'the active sub nav should be Hooks' do step 'the active sub nav should be Hooks' do
ensure_active_sub_nav('Webhooks') ensure_active_sub_nav('Webhooks')
end end
...@@ -56,8 +54,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -56,8 +54,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end end
step 'I click the "Branches" tab' do step 'I click the "Branches" tab' do
page.within '.content' do
click_link('Branches') click_link('Branches')
end end
end
step 'I click the "Tags" tab' do step 'I click the "Tags" tab' do
click_link('Tags') click_link('Tags')
...@@ -82,12 +82,16 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps ...@@ -82,12 +82,16 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Issues # Sub Tabs: Issues
step 'I click the "Milestones" tab' do step 'I click the "Milestones" tab' do
page.within('.layout-nav') do
click_link('Milestones') click_link('Milestones')
end end
end
step 'I click the "Labels" tab' do step 'I click the "Labels" tab' do
page.within('.layout-nav') do
click_link('Labels') click_link('Labels')
end end
end
step 'the active sub tab should be Issues' do step 'the active sub tab should be Issues' do
ensure_active_sub_tab('Issues') ensure_active_sub_tab('Issues')
......
...@@ -105,7 +105,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps ...@@ -105,7 +105,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end end
step 'I should not see button to create a new merge request' do step 'I should not see button to create a new merge request' do
expect(page).to_not have_link 'Create Merge Request' expect(page).not_to have_link 'Create Merge Request'
end end
step 'I should see button to the merge request' do step 'I should see button to the merge request' do
......
...@@ -36,7 +36,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps ...@@ -36,7 +36,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
end end
step 'I goto the Merge Requests page' do step 'I goto the Merge Requests page' do
page.within '.page-sidebar-expanded' do page.within '.layout-nav' do
click_link "Merge Requests" click_link "Merge Requests"
end end
end end
......
...@@ -39,8 +39,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps ...@@ -39,8 +39,8 @@ class Spinach::Features::AwardEmoji < Spinach::FeatureSteps
step 'I can see the activity and food categories' do step 'I can see the activity and food categories' do
page.within '.emoji-menu' do page.within '.emoji-menu' do
expect(page).to_not have_selector 'Activity' expect(page).not_to have_selector 'Activity'
expect(page).to_not have_selector 'Food' expect(page).not_to have_selector 'Food'
end end
end end
......
...@@ -216,7 +216,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -216,7 +216,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
page.within 'li.issue:nth-child(3)' do page.within 'li.issue:nth-child(3)' do
expect(page).to have_content 'Bugfix' expect(page).to have_content 'Bugfix'
expect(page).to_not have_content '0 0' expect(page).not_to have_content '0 0'
end end
end end
end end
...@@ -235,7 +235,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps ...@@ -235,7 +235,7 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps
page.within 'li.issue:nth-child(3)' do page.within 'li.issue:nth-child(3)' do
expect(page).to have_content 'Bugfix' expect(page).to have_content 'Bugfix'
expect(page).to_not have_content '0 0' expect(page).not_to have_content '0 0'
end end
end end
end end
......
...@@ -24,8 +24,8 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps ...@@ -24,8 +24,8 @@ class Spinach::Features::ProjectIssuesLabels < Spinach::FeatureSteps
step 'I should see labels help message' do step 'I should see labels help message' do
page.within '.labels' do page.within '.labels' do
expect(page).to have_content 'Create first label or generate default set of '\ expect(page).to have_content 'Create a label or generate a default set '\
'labels' 'of labels'
end end
end end
......
...@@ -203,7 +203,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -203,7 +203,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
page.within 'li.merge-request:nth-child(3)' do page.within 'li.merge-request:nth-child(3)' do
expect(page).to have_content 'Bug NS-05' expect(page).to have_content 'Bug NS-05'
expect(page).to_not have_content '0 0' expect(page).not_to have_content '0 0'
end end
end end
end end
...@@ -222,7 +222,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps ...@@ -222,7 +222,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps
page.within 'li.merge-request:nth-child(3)' do page.within 'li.merge-request:nth-child(3)' do
expect(page).to have_content 'Bug NS-05' expect(page).to have_content 'Bug NS-05'
expect(page).to_not have_content '0 0' expect(page).not_to have_content '0 0'
end end
end end
end end
......
...@@ -114,8 +114,10 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -114,8 +114,10 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end end
step 'I should not see "Snippets" button' do step 'I should not see "Snippets" button' do
page.within '.content' do
expect(page).not_to have_link 'Snippets' expect(page).not_to have_link 'Snippets'
end end
end
step 'project "Shop" belongs to group' do step 'project "Shop" belongs to group' do
group = create(:group) group = create(:group)
...@@ -123,14 +125,6 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -123,14 +125,6 @@ class Spinach::Features::Project < Spinach::FeatureSteps
@project.save! @project.save!
end end
step 'I should see back to dashboard button' do
expect(page).to have_content 'Go to dashboard'
end
step 'I should see back to group button' do
expect(page).to have_content 'Go to group'
end
step 'I click notifications drop down button' do step 'I click notifications drop down button' do
click_link 'notifications-button' click_link 'notifications-button'
end end
......
...@@ -52,7 +52,7 @@ class Spinach::Features::ProjectMilestone < Spinach::FeatureSteps ...@@ -52,7 +52,7 @@ class Spinach::Features::ProjectMilestone < Spinach::FeatureSteps
end end
step 'I click link "Labels"' do step 'I click link "Labels"' do
page.within('.nav-links') do page.within('.layout-nav .nav-links') do
page.find(:xpath, "//a[@href='#tab-labels']").click page.find(:xpath, "//a[@href='#tab-labels']").click
end end
end end
......
...@@ -3,6 +3,7 @@ class Spinach::Features::ProjectShortcuts < Spinach::FeatureSteps ...@@ -3,6 +3,7 @@ class Spinach::Features::ProjectShortcuts < Spinach::FeatureSteps
include SharedPaths include SharedPaths
include SharedProject include SharedProject
include SharedProjectTab include SharedProjectTab
include SharedShortcuts
step 'I press "g" and "f"' do step 'I press "g" and "f"' do
find('body').native.send_key('g') find('body').native.send_key('g')
......
...@@ -43,12 +43,12 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps ...@@ -43,12 +43,12 @@ class Spinach::Features::ProjectSnippets < Spinach::FeatureSteps
step 'I click link "Edit"' do step 'I click link "Edit"' do
page.within ".detail-page-header" do page.within ".detail-page-header" do
click_link "Edit" first(:link, "Edit").click
end end
end end
step 'I click link "Delete"' do step 'I click link "Delete"' do
click_link "Delete" first(:link, "Delete").click
end end
step 'I submit new snippet "Snippet three"' do step 'I submit new snippet "Snippet three"' do
......
...@@ -337,6 +337,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps ...@@ -337,6 +337,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end end
step 'I should see buttons for allowed commands' do step 'I should see buttons for allowed commands' do
page.within '.content' do
expect(page).to have_content 'Raw' expect(page).to have_content 'Raw'
expect(page).to have_content 'History' expect(page).to have_content 'History'
expect(page).to have_content 'Permalink' expect(page).to have_content 'Permalink'
...@@ -345,6 +346,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps ...@@ -345,6 +346,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
expect(page).to have_content 'Delete' expect(page).to have_content 'Delete'
expect(page).to have_content 'Replace' expect(page).to have_content 'Replace'
end end
end
step 'I should see a notice about a new fork having been created' do step 'I should see a notice about a new fork having been created' do
expect(page).to have_content "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request." expect(page).to have_content "You're not allowed to make changes to this project directly. A fork of this project has been created that you can make changes in, so you can submit a merge request."
......
...@@ -2,7 +2,7 @@ module SharedActiveTab ...@@ -2,7 +2,7 @@ module SharedActiveTab
include Spinach::DSL include Spinach::DSL
def ensure_active_main_tab(content) def ensure_active_main_tab(content)
expect(find('.nav-sidebar > li.active')).to have_content(content) expect(find('.layout-nav li.active')).to have_content(content)
end end
def ensure_active_sub_tab(content) def ensure_active_sub_tab(content)
...@@ -10,11 +10,11 @@ module SharedActiveTab ...@@ -10,11 +10,11 @@ module SharedActiveTab
end end
def ensure_active_sub_nav(content) def ensure_active_sub_nav(content)
expect(find('.sidebar-subnav > li.active')).to have_content(content) expect(find('.layout-nav .controls li.active')).to have_content(content)
end end
step 'no other main tabs should be active' do step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1) expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 1)
end end
step 'no other sub tabs should be active' do step 'no other sub tabs should be active' do
...@@ -22,26 +22,6 @@ module SharedActiveTab ...@@ -22,26 +22,6 @@ module SharedActiveTab
end end
step 'no other sub navs should be active' do step 'no other sub navs should be active' do
expect(page).to have_selector('.sidebar-subnav > li.active', count: 1) expect(page).to have_selector('.layout-nav .controls li.active', count: 1)
end
step 'the active main tab should be Home' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Projects' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Issues' do
ensure_active_main_tab('Issues')
end
step 'the active main tab should be Merge Requests' do
ensure_active_main_tab('Merge Requests')
end
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end end
end end
...@@ -111,7 +111,7 @@ module SharedIssuable ...@@ -111,7 +111,7 @@ module SharedIssuable
step 'I sort the list by "Oldest updated"' do step 'I sort the list by "Oldest updated"' do
find('button.dropdown-toggle.btn').click find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link "Oldest updated" click_link "Oldest updated"
end end
end end
...@@ -119,7 +119,7 @@ module SharedIssuable ...@@ -119,7 +119,7 @@ module SharedIssuable
step 'I sort the list by "Least popular"' do step 'I sort the list by "Least popular"' do
find('button.dropdown-toggle.btn').click find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Least popular' click_link 'Least popular'
end end
end end
...@@ -127,13 +127,13 @@ module SharedIssuable ...@@ -127,13 +127,13 @@ module SharedIssuable
step 'I sort the list by "Most popular"' do step 'I sort the list by "Most popular"' do
find('button.dropdown-toggle.btn').click find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Most popular' click_link 'Most popular'
end end
end end
step 'The list should be sorted by "Oldest updated"' do step 'The list should be sorted by "Oldest updated"' do
page.within('div.dropdown.inline.prepend-left-10') do page.within('.content div.dropdown.inline.prepend-left-10') do
expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated') expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated')
end end
end end
......
...@@ -107,7 +107,7 @@ module SharedNote ...@@ -107,7 +107,7 @@ module SharedNote
end end
step 'I should see no notes at all' do step 'I should see no notes at all' do
expect(page).to_not have_css('.note') expect(page).not_to have_css('.note')
end end
# Markdown # Markdown
......
...@@ -95,7 +95,7 @@ module SharedProject ...@@ -95,7 +95,7 @@ module SharedProject
step 'I should see project settings' do step 'I should see project settings' do
expect(current_path).to eq edit_namespace_project_path(@project.namespace, @project) expect(current_path).to eq edit_namespace_project_path(@project.namespace, @project)
expect(page).to have_content("Project name") expect(page).to have_content("Project name")
expect(page).to have_content("Features:") expect(page).to have_content("Features")
end end
def current_project def current_project
......
...@@ -41,9 +41,7 @@ module SharedProjectTab ...@@ -41,9 +41,7 @@ module SharedProjectTab
end end
step 'the active main tab should be Settings' do step 'the active main tab should be Settings' do
page.within '.nav-sidebar' do expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 0)
expect(page).to have_content('Go to project')
end
end end
step 'the active main tab should be Activity' do step 'the active main tab should be Activity' do
......
module SharedActiveTab module SharedShortcuts
include Spinach::DSL include Spinach::DSL
step 'I press "g" and "p"' do step 'I press "g" and "p"' do
......
module SharedSidebarActiveTab
include Spinach::DSL
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
end
def ensure_active_main_tab(content)
expect(find('.nav-sidebar li.active')).to have_content(content)
end
step 'the active main tab should be Home' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Projects' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Issues' do
ensure_active_main_tab('Issues')
end
step 'the active main tab should be Merge Requests' do
ensure_active_main_tab('Merge Requests')
end
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
end
...@@ -14,12 +14,12 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps ...@@ -14,12 +14,12 @@ class Spinach::Features::Snippets < Spinach::FeatureSteps
step 'I click link "Edit"' do step 'I click link "Edit"' do
page.within ".detail-page-header" do page.within ".detail-page-header" do
click_link "Edit" first(:link, "Edit").click
end end
end end
step 'I click link "Delete"' do step 'I click link "Delete"' do
click_link "Delete" first(:link, "Delete").click
end end
step 'I submit new snippet "Personal snippet three"' do step 'I submit new snippet "Personal snippet three"' do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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