diff options
46 files changed, 633 insertions, 308 deletions
diff --git a/CHANGELOG b/CHANGELOG index b7e8822fdd6..d43b8f69063 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,6 +13,7 @@ v 8.5.0 (unreleased) set it up - Fix diff comments loaded by AJAX to load comment with diff in discussion tab - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) + - Fix label links for a merge request pointing to issues list - Don't vendor minified JS - Display 404 error on group not found - Track project import failure diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee index d5e6ff0717a..e54bfce058a 100644 --- a/app/assets/javascripts/application.js.coffee +++ b/app/assets/javascripts/application.js.coffee @@ -215,4 +215,76 @@ $ -> $this = $(this) $this.attr 'value', $this.val() + $(document).on 'breakpoint:change', (e, breakpoint) -> + if breakpoint is 'sm' or breakpoint is 'xs' + $gutterIcon = $('.gutter-toggle').find('i') + if $gutterIcon.hasClass('fa-angle-double-right') + $gutterIcon.closest('a').trigger('click') + + + $(document).on 'click', 'aside .gutter-toggle', (e) -> + e.preventDefault() + $this = $(this) + $thisIcon = $this.find 'i' + if $thisIcon.hasClass('fa-angle-double-right') + $thisIcon.removeClass('fa-angle-double-right') + .addClass('fa-angle-double-left') + $this + .closest('aside') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + $('.page-with-sidebar') + .removeClass('right-sidebar-expanded') + .addClass('right-sidebar-collapsed') + else + $thisIcon.removeClass('fa-angle-double-left') + .addClass('fa-angle-double-right') + $this + .closest('aside') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $('.page-with-sidebar') + .removeClass('right-sidebar-collapsed') + .addClass('right-sidebar-expanded') + $.cookie("collapsed_gutter", + $('.right-sidebar') + .hasClass('right-sidebar-collapsed'), { path: '/' }) + + bootstrapBreakpoint = undefined; + checkBootstrapBreakpoints = -> + if $('.device-xs').is(':visible') + bootstrapBreakpoint = "xs" + else if $('.device-sm').is(':visible') + bootstrapBreakpoint = "sm" + else if $('.device-md').is(':visible') + bootstrapBreakpoint = "md" + else if $('.device-lg').is(':visible') + bootstrapBreakpoint = "lg" + + setBootstrapBreakpoints = -> + if $('.device-xs').length + return + + $("body") + .append('<div class="device-xs visible-xs"></div>'+ + '<div class="device-sm visible-sm"></div>'+ + '<div class="device-md visible-md"></div>'+ + '<div class="device-lg visible-lg"></div>') + checkBootstrapBreakpoints() + + fitSidebarForSize = -> + oldBootstrapBreakpoint = bootstrapBreakpoint + checkBootstrapBreakpoints() + if bootstrapBreakpoint != oldBootstrapBreakpoint + $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) + + checkInitialSidebarSize = -> + if bootstrapBreakpoint is "xs" or "sm" + $(document).trigger('breakpoint:change', [bootstrapBreakpoint]) + + $(window).on "resize", (e) -> + fitSidebarForSize() + + setBootstrapBreakpoints() + checkInitialSidebarSize() new Aside() diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index 02232698bc2..d17b1123418 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -10,19 +10,7 @@ class @IssuableContext $(".issuable-sidebar .inline-update").on "change", ".js-assignee", -> $(this).submit() - $('.issuable-details').waitForImages -> - $('.issuable-affix').on 'affix.bs.affix', -> - $(@).width($(@).outerWidth()) - .on 'affixed-top.bs.affix affixed-bottom.bs.affix', -> - $(@).width('') - - $('.issuable-affix').affix offset: - top: -> - @top = ($('.issuable-affix').offset().top - 70) - bottom: -> - @bottom = $('.footer').outerHeight(true) - - $(".edit-link").click (e) -> + $(document).on "click",".edit-link", (e) -> block = $(@).parents('.block') block.find('.selectbox').show() block.find('.value').hide() diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 36e582d4854..b7ffa3e6ffb 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -24,6 +24,7 @@ &.s26 { width: 26px; height: 26px; margin-right: 8px; } &.s32 { width: 32px; height: 32px; margin-right: 10px; } &.s36 { width: 36px; height: 36px; margin-right: 10px; } + &.s40 { width: 40px; height: 40px; margin-right: 10px; } &.s46 { width: 46px; height: 46px; margin-right: 15px; } &.s48 { width: 48px; height: 48px; margin-right: 10px; } &.s60 { width: 60px; height: 60px; margin-right: 12px; } @@ -40,7 +41,8 @@ &.s16 { font-size: 12px; line-height: 1.33; } &.s24 { font-size: 14px; line-height: 1.8; } &.s26 { font-size: 20px; line-height: 1.33; } - &.s32 { font-size: 22px; line-height: 32px; } + &.s32 { font-size: 20px; line-height: 32px; } + &.s40 { font-size: 16px; line-height: 40px; } &.s60 { font-size: 32px; line-height: 60px; } &.s90 { font-size: 36px; line-height: 90px; } &.s110 { font-size: 40px; line-height: 112px; font-weight: 300; } diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 11df4c24056..5f193fa7434 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -2,7 +2,7 @@ @include border-radius(3px); font-size: $gl-font-size; font-weight: 500; - padding: $gl-vert-padding $gl-padding; + padding: $gl-vert-padding $gl-btn-padding; &:focus, &:active { diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index e93dbab0c42..08dcb563dce 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -9,7 +9,7 @@ display: block; float: left; - padding: 0 $gl-padding; + padding: 0 $gl-btn-padding; font-weight: normal; margin-right: 10px; font-size: $gl-font-size; diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index c6bc6fb324d..5c65383ec1a 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -109,7 +109,6 @@ ul.content-list { padding: 0; > li { - padding: $gl-padding 0; border-color: $table-border-color; color: $gl-gray; diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index 0997dfc287c..3bfac2ad9b5 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -116,7 +116,7 @@ display: none; } - aside { + aside:not(.right-sidebar){ display: none; } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 540d0b03163..b7f532c0771 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -200,6 +200,14 @@ } } +@mixin expanded-gutter { + padding-right: $gutter_width; +} + +@mixin collapsed-gutter { + padding-right: $sidebar_collapsed_width; +} + @mixin collapsed-sidebar { padding-left: $sidebar_collapsed_width; @@ -266,6 +274,7 @@ background: #f2f6f7; } +// page is small enough @media (max-width: $screen-md-max) { .page-sidebar-collapsed { @include collapsed-sidebar; @@ -275,12 +284,32 @@ @include collapsed-sidebar; } + .page-gutter { + &.right-sidebar-collapsed { + @include collapsed-gutter; + } + &.right-sidebar-expanded { + @include expanded-gutter; + } + } + .collapse-nav { display: none; } } +// page is large enough @media(min-width: $screen-md-max) { + + .page-gutter { + &.right-sidebar-collapsed { + @include collapsed-gutter; + } + &.right-sidebar-expanded { + @include expanded-gutter; + } + } + .page-sidebar-collapsed { @include collapsed-sidebar; } @@ -288,4 +317,4 @@ .page-sidebar-expanded { @include expanded-sidebar; } -} +}
\ No newline at end of file diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 3ec48da9a41..efc3366e99c 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -12,6 +12,9 @@ $gl-font-size: 15px; $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; +$gutter_collapsed_width: 62px; +$gutter_width: 312px; +$gutter_inner_width: 280px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; @@ -22,9 +25,10 @@ $header-height: 58px; $fixed-layout-width: 1280px; $gl-gray: #5a5a5a; $gl-padding: 16px; +$gl-btn-padding: 10px; $gl-vert-padding: 6px; $gl-padding-top:10px; -$gl-avatar-size: 46px; +$gl-avatar-size: 40px; $secondary-text: #7f8fa4; $error-exclamation-point: #E62958; @@ -36,11 +40,12 @@ $white-light: #FFFFFF; $white-normal: #ededed; $white-dark: #ededed; -$gray-light: #f7f7f7; -$gray-normal: #ededed; +$gray-light: #faf9f9; +$gray-normal: #f5f5f5; $gray-dark: #ededed; +$gray-darkest: #c9c9c9; -$green-light: #31AF64; +$green-light: #38ae67; $green-normal: #2FAA60; $green-dark: #2CA05B; @@ -52,7 +57,7 @@ $blue-medium-light: #3498CB; $blue-medium: #2F8EBF; $blue-medium-dark: #2D86B4; -$orange-light: #FC6443; +$orange-light: rgba(252, 109, 38, 0.80); $orange-normal: #E75E40; $orange-dark: #CE5237; @@ -64,8 +69,8 @@ $border-white-light: #F1F2F4; $border-white-normal: #D6DAE2; $border-white-dark: #C6CACF; -$border-gray-light: #d1d1d1; -$border-gray-normal: #D6DAE2; +$border-gray-light: rgba(0, 0, 0, 0.06); +$border-gray-normal: rgba(0, 0, 0, 0.10);; $border-gray-dark: #C6CACF; $border-green-light: #2FAA60; @@ -76,7 +81,7 @@ $border-blue-light: #2D9FD8; $border-blue-normal: #2897CE; $border-blue-dark: #258DC1; -$border-orange-light: #ED5C3D; +$border-orange-light: #fc6d26; $border-orange-normal: #CE5237; $border-orange-dark: #C14E35; diff --git a/app/assets/stylesheets/pages/dashboard.scss b/app/assets/stylesheets/pages/dashboard.scss index 25a86cd0f94..88639399148 100644 --- a/app/assets/stylesheets/pages/dashboard.scss +++ b/app/assets/stylesheets/pages/dashboard.scss @@ -40,10 +40,6 @@ .avatar { @include border-radius(50%); } - - .identicon { - line-height: 46px; - } } .dash-project-access-icon { diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index 8fa15b35748..35df9a61c86 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -4,7 +4,7 @@ */ .event-item { font-size: $gl-font-size; - padding: $gl-padding 0 $gl-padding ($gl-avatar-size + 15px); + padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); border-bottom: 1px solid $table-border-color; color: #7f8fa4; @@ -16,7 +16,7 @@ .event-title, .event-item-timestamp { - line-height: 44px; + line-height: 40px; } } @@ -25,7 +25,7 @@ } .avatar { - margin-left: -($gl-avatar-size + 15px); + margin-left: -($gl-avatar-size + $gl-padding-top); } .event-title { @@ -41,7 +41,6 @@ margin-right: 174px; .event-note { - margin-top: 5px; word-wrap: break-word; .md { @@ -98,8 +97,6 @@ &:last-child { border:none } .event_commits { - margin-top: 9px; - li { &.commit { background: transparent; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 977ada0ff38..e5026489167 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -29,21 +29,8 @@ } } -.project-issuable-filter { - .controls { - float: right; - margin-top: 11px; - } - - .nav-links { - text-align: left; - } -} - .issuable-details { section { - border-right: 1px solid $border-white-light; - .issuable-discussion { margin-right: 1px; } @@ -73,11 +60,35 @@ .block { @include clearfix; padding: $gl-padding 0; - border-bottom: 1px solid #F0F0F0; + border-bottom: 1px solid $border-gray-light; + // This prevents the mess when resizing the sidebar + // of elements repositioning themselves.. + width: $gutter_inner_width; + overflow-x: hidden; + // -- + + &:first-child { + padding-top: 5px; + } &:last-child { border: none; } + + span { + margin-top: 7px; + display: inline-block; + } + + .issuable-count { + + } + + .gutter-toggle { + margin-left: 20px; + border-left: 1px solid $border-gray-light; + padding-left: 10px; + } } .title { @@ -133,3 +144,92 @@ margin-right: 2px; } } + + +.right-sidebar { + position: fixed; + top: 58px; + right: 0; + height: 100%; + transition-duration: .3s; + background: $gray-light; + overflow: scroll; + padding: 10px 20px; + + &.right-sidebar-expanded { + width: $gutter_width; + + hr { + display: none; + } + } + + .subscribe-button { + span { + margin-top: 0; + } + } + + &.right-sidebar-collapsed { + width: $sidebar_collapsed_width; + padding-top: 0; + overflow-x: hidden; + + hr { + margin: 0; + color: $gray-normal; + border-color: $gray-normal; + width: 62px; + margin-left: -20px + } + + .block { + border-bottom: none; + padding: 15px 0 0 0; + } + } + + .btn { + background: $gray-normal; + border: 1px solid $border-gray-normal; + } + + &.right-sidebar-collapsed { + .issuable-count, + .issuable-nav, + .assignee > *, + .milestone > *, + .labels > *, + .participants > *, + .light > *, + .project-reference > * { + display: none; + } + + .gutter-toggle { + margin-left: -$gutter_inner_width + 4; + } + + .sidebar-collapsed-icon { + display: block; + float: left; + width: 62px; + text-align: center; + margin-left: -19px; + padding-bottom: 10px; + color: #999999; + + span { + display: block; + margin-top: 0; + } + } + + } + + &.right-sidebar-expanded { + .sidebar-collapsed-icon { + display: none; + } + } +} diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index dd6a251f811..8694bd654a7 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -65,10 +65,6 @@ form.edit-issue { width: 3em; } -.merge-request-info { - padding-left: 5px; -} - .merge-request-status { color: $gl-gray; font-size: 15px; @@ -143,4 +139,4 @@ form.edit-issue { .issue-closed-by-widget { color: $secondary-text; margin-left: 52px; -}
\ No newline at end of file +} diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index dd4ff39c5b8..046bae672fc 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -391,12 +391,11 @@ pre.light-well { @include basic-list; .project-row { - padding: $gl-padding 0; border-color: $table-border-color; &.no-description { .project { - line-height: 44px; + line-height: 40px; } } @@ -409,7 +408,7 @@ pre.light-well { .project-controls { float: right; color: $gl-gray; - line-height: 45px; + line-height: 40px; color: #7f8fa4; a:hover { diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a2458ad3be0..622cbfe3cc4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -169,18 +169,6 @@ module ApplicationHelper Gitlab.config.extra end - def search_placeholder - if @project && @project.persisted? - 'Search' - elsif @snippet || @snippets || @show_snippets - 'Search snippets' - elsif @group && @group.persisted? - 'Search in this group' - else - 'Search' - end - end - # Render a `time` element with Javascript-based relative date and tooltip # # time - Time object @@ -293,6 +281,76 @@ module ApplicationHelper end end + def issuable_link_next(project,issuable) + if project.nil? + nil + elsif current_controller?(:issues) + namespace_project_issue_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) + elsif current_controller?(:merge_requests) + namespace_project_merge_request_path(project.namespace, project, next_issuable_for(project, issuable.id).try(:iid)) + end + end + + def issuable_link_prev(project,issuable) + if project.nil? + nil + elsif current_controller?(:issues) + namespace_project_issue_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) + elsif current_controller?(:merge_requests) + namespace_project_merge_request_path(project.namespace, project, prev_issuable_for(project, issuable.id).try(:iid)) + end + end + + def issuable_count(entity, project) + if project.nil? + 0 + elsif current_controller?(:issues) + project.issues.send(entity).count + elsif current_controller?(:merge_requests) + project.merge_requests.send(entity).count + end + end + + def next_issuable_for(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id > ?", id).last + elsif current_controller?(:merge_requests) + project.merge_requests.where("id > ?", id).last + end + end + + def has_next_issuable?(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id > ?", id).last + elsif current_controller?(:merge_requests) + project.merge_requests.where("id > ?", id).last + end + end + + def prev_issuable_for(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id < ?", id).first + elsif current_controller?(:merge_requests) + project.merge_requests.where("id < ?", id).first + end + end + + def has_prev_issuable?(project, id) + if project.nil? + nil + elsif current_controller?(:issues) + project.issues.where("id < ?", id).first + elsif current_controller?(:merge_requests) + project.merge_requests.where("id < ?", id).first + end + end + def state_filters_text_for(entity, project) titles = { opened: "Open" diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index 92eac0560bd..1c7fcc13b42 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -7,6 +7,8 @@ module LabelsHelper # project - Project object which will be used as the context for the label's # link. If omitted, defaults to `@project`, or the label's own # project. + # type - The type of item the link will point to (:issue or + # :merge_request). If omitted, defaults to :issue. # block - An optional block that will be passed to `link_to`, forming the # body of the link element. If omitted, defaults to # `render_colored_label`. @@ -23,14 +25,19 @@ module LabelsHelper # # Force the generated link to use a provided project # link_to_label(label, project: Project.last) # + # # Force the generated link to point to merge requests instead of issues + # link_to_label(label, type: :merge_request) + # # # Customize link body with a block # link_to_label(label) { "My Custom Label Text" } # # Returns a String - def link_to_label(label, project: nil, &block) + def link_to_label(label, project: nil, type: :issue, &block) project ||= @project || label.project - link = namespace_project_issues_path(project.namespace, project, - label_name: label.name) + link = send("namespace_project_#{type.to_s.pluralize}_path", + project.namespace, + project, + label_name: label.name) if block_given? link_to link, &block diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index e6fb8670e57..2c299d1d794 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -3,6 +3,18 @@ module NavHelper cookies[:collapsed_nav] == 'true' end + def sidebar_gutter_collapsed_class + if cookies[:collapsed_gutter] == 'true' + "right-sidebar-collapsed" + else + "right-sidebar-expanded" + end + end + + def sidebar_gutter_collapsed? + cookies[:collapsed_gutter] == 'true' + end + def nav_sidebar_class if nav_menu_collapsed? "sidebar-collapsed" @@ -19,6 +31,17 @@ module NavHelper end end + def page_gutter_class + + if current_path?('merge_requests#show') || current_path?('issues#show') + if cookies[:collapsed_gutter] == 'true' + "page-gutter right-sidebar-collapsed" + else + "page-gutter right-sidebar-expanded" + end + end + end + def nav_header_class if nav_menu_collapsed? "header-collapsed" diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index dc487a31d97..2e9741a8622 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -20,6 +20,12 @@ module ProjectsHelper end end + def link_to_member_avatar(author, opts = {}) + default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } + opts = default_opts.merge(opts) + image_tag(avatar_icon(author, opts[:size]), width: opts[:size], class: "avatar avatar-inline #{"s#{opts[:size]}" if opts[:size]}", alt:'') if opts[:avatar] + end + def link_to_member(project, author, opts = {}) default_opts = { avatar: true, name: true, size: 16, author_class: 'author', title: ":name" } opts = default_opts.merge(opts) diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml index ebf2b7b60e7..5931efdefe6 100644 --- a/app/views/admin/builds/index.html.haml +++ b/app/views/admin/builds/index.html.haml @@ -1,9 +1,4 @@ -.project-issuable-filter - .controls - .pull-left.hidden-xs - - if @all_builds.running_or_pending.any? - = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - +.top-area %ul.nav-links %li{class: ('active' if @scope.nil?)} = link_to admin_builds_path do @@ -20,7 +15,11 @@ Finished %span.badge.js-running-count= number_with_delimiter(@all_builds.finished.count(:id)) -.gray-content-block + .nav-controls + - if @all_builds.running_or_pending.any? + = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + +.gray-content-block.second-block #{(@scope || 'running').capitalize} builds %ul.content-list diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index f363f035974..dfa5f80eef8 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -4,17 +4,15 @@ - if current_user = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to issues_dashboard_url(format: :atom, private_token: current_user.private_token), class: 'btn' do + = icon('rss') = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .prepend-top-default = render 'shared/issues' diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index bbe4cc1f824..fb016599fef 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,11 +1,12 @@ - page_title "Merge Requests" - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) -.project-issuable-filter - .controls +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" - = render 'shared/issuable/filter', type: :merge_requests += render 'shared/issuable/filter', type: :merge_requests .prepend-top-default = render 'shared/merge_requests' diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 46432a92348..36fb2d51629 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -3,8 +3,8 @@ .event-item-timestamp #{time_ago_with_tooltip(event.created_at)} - = cache [event, current_application_settings, "v2.1"] do - = image_tag avatar_icon(event.author_email, 46), class: "avatar s46", alt:'' + = cache [event, current_application_settings, "v2.2"] do + = image_tag avatar_icon(event.author_email, 40), class: "avatar s40", alt:'' - if event.created_project? = render "events/event/created_project", event: event - elsif event.push? diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index 90ade1e1680..b0805593fdc 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -4,17 +4,15 @@ - if current_user = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to issues_group_url(@group, format: :atom, private_token: current_user.private_token), class: 'btn' do + = icon('rss') = render 'shared/new_project_item_select', path: 'issues/new', label: "New Issue" - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .gray-content-block.second-block Only issues from diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index f662f5a8c17..e1c9dd931ee 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -1,11 +1,12 @@ - page_title "Merge Requests" - header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group)) -.project-issuable-filter - .controls +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New Merge Request" - = render 'shared/issuable/filter', type: :merge_requests += render 'shared/issuable/filter', type: :merge_requests .gray-content-block.second-block Only merge requests from diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml index 9ee6f07b26b..8e982718d23 100644 --- a/app/views/help/_shortcuts.html.haml +++ b/app/views/help/_shortcuts.html.haml @@ -40,10 +40,6 @@ %td.shortcut .key enter %td Open Selection - %tr - %td.shortcut - .key t - %td Go to finding file %tbody %tr %th @@ -161,6 +157,10 @@ .key s %td Go to snippets + %tr + %td.shortcut + .key t + %td Go to finding file .col-lg-4 %table.shortcut-mappings %tbody{ class: 'hidden-shortcut network', style: 'display:none' } diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 26159989777..0c1b5eec95a 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,4 +1,4 @@ -.page-with-sidebar{ class: page_sidebar_class } +.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } = render "layouts/broadcast" .sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .header-logo diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index a44f5762a6b..659f5a7756b 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -1,6 +1,6 @@ .search = form_tag search_path, method: :get, class: 'navbar-form pull-left' do |f| - = search_field_tag "search", nil, placeholder: search_placeholder, class: "search-input form-control", spellcheck: false + = search_field_tag "search", nil, placeholder: 'search', class: "search-input form-control", spellcheck: false = hidden_field_tag :group_id, @group.try(:id) - if @project && @project.persisted? = hidden_field_tag :project_id, @project.id diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index d6260ab2900..fde9304c0f8 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -5,22 +5,19 @@ - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") -.project-issuable-filter - .controls - .pull-left - - if current_user - .hidden-xs.pull-left - = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do - %i.fa.fa-rss - +.top-area + = render 'shared/issuable/nav', type: :issues + .nav-controls + - if current_user + = link_to namespace_project_issues_path(@project.namespace, @project, :atom, { private_token: current_user.private_token }), class: 'btn append-right-10' do + = icon('rss') = render 'shared/issuable/search_form', path: namespace_project_issues_path(@project.namespace, @project) - - if can? current_user, :create_issue, @project - = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new pull-left", title: "New Issue", id: "new_issue_link" do - %i.fa.fa-plus + = link_to new_namespace_project_issue_path(@project.namespace, @project, issue: { assignee_id: @issuable_finder.assignee.try(:id), milestone_id: @issuable_finder.milestones.try(:first).try(:id) }), class: "btn btn-new", title: "New Issue", id: "new_issue_link" do + = icon('plus') New Issue - = render 'shared/issuable/filter', type: :issues += render 'shared/issuable/filter', type: :issues .issues-holder = render "issues" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 51dcca7a1ab..030f4a2e644 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -54,11 +54,8 @@ = render 'votes/votes_block', votable: @issue .row - %section.col-md-9 + %section.col-md-12 .issuable-discussion = render 'projects/issues/discussion' - %aside.col-md-3 - = render 'shared/issuable/sidebar', issuable: @issue - - = render 'shared/show_aside' += render 'shared/issuable/sidebar', issuable: @issue
\ No newline at end of file diff --git a/app/views/projects/issues/update.js.haml b/app/views/projects/issues/update.js.haml index 2f0f3fcfb06..a54733883b4 100644 --- a/app/views/projects/issues/update.js.haml +++ b/app/views/projects/issues/update.js.haml @@ -1,3 +1,3 @@ -$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"); -$('.issuable-sidebar').parent().effect('highlight') -new Issue(); +$('aside.right-sidebar')[0].outerHTML = "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @issue)}"; +$('aside.right-sidebar').effect('highlight'); +new Issue();
\ No newline at end of file diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index a051729dc32..e25bf917b43 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -53,7 +53,7 @@ - if merge_request.labels.any? - merge_request.labels.each do |label| - = link_to_label(label, project: merge_request.project) + = link_to_label(label, project: merge_request.project, type: 'merge_request') - if merge_request.tasks? %span.task-status diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 8641c3d8b4b..da67645bc2b 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -70,12 +70,9 @@ = render 'votes/votes_block', votable: @merge_request .row - %section.col-md-9 + %section.col-md-12 .issuable-discussion = render "projects/merge_requests/discussion" - %aside.col-md-3 - = render 'shared/issuable/sidebar', issuable: @merge_request - = render 'shared/show_aside' #commits.commits.tab-pane - # This tab is always loaded via AJAX @@ -87,6 +84,8 @@ .mr-loading-status = spinner += render 'shared/issuable/sidebar', issuable: @merge_request + :javascript var merge_request; diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 8d5d0394a82..e56a44e0a79 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -2,16 +2,19 @@ = render "header_title" = render 'projects/last_push' -.project-issuable-filter - .controls + +.top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls = render 'shared/issuable/search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) - merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project)) - if merge_project - .pull-left.hidden-xs - = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do - %i.fa.fa-plus - New Merge Request - = render 'shared/issuable/filter', type: :merge_requests + = link_to new_namespace_project_merge_request_path(merge_project.namespace, merge_project), class: "btn btn-new", title: "New Merge Request" do + = icon('plus') + New Merge Request + += render 'shared/issuable/filter', type: :merge_requests + .merge-requests-holder = render 'merge_requests' diff --git a/app/views/projects/merge_requests/update.js.haml b/app/views/projects/merge_requests/update.js.haml index 93db65ddf79..ce5157d69a2 100644 --- a/app/views/projects/merge_requests/update.js.haml +++ b/app/views/projects/merge_requests/update.js.haml @@ -1,3 +1,3 @@ -$('.issuable-sidebar').html("#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"); -$('.issuable-sidebar').parent().effect('highlight') +$('aside.right-sidebar')[0].outerHTML= "#{escape_javascript(render 'shared/issuable/sidebar', issuable: @merge_request)}"; +$('aside.right-sidebar').effect('highlight') merge_request = new MergeRequest(); diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index f7fe6b02641..289b0bfe1eb 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -21,7 +21,7 @@ = icon('users') = number_with_delimiter(group.users.count) - = image_tag group_icon(group), class: "avatar s46 hidden-xs" + = image_tag group_icon(group), class: "avatar s40 hidden-xs" = link_to group, class: 'group-name' do %span.item-title= group.name diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml index 8d6f47b38ef..b7e350d27af 100644 --- a/app/views/shared/issuable/_filter.html.haml +++ b/app/views/shared/issuable/_filter.html.haml @@ -1,32 +1,5 @@ .issues-filters - .issues-state-filters - %ul.nav-links - - if defined?(type) && type == :merge_requests - - page_context_word = 'merge requests' - - else - - page_context_word = 'issues' - %li{class: ("active" if params[:state] == 'opened')} - = link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do - #{state_filters_text_for(:opened, @project)} - - - if defined?(type) && type == :merge_requests - %li{class: ("active" if params[:state] == 'merged')} - = link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do - #{state_filters_text_for(:merged, @project)} - - %li{class: ("active" if params[:state] == 'closed')} - = link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do - #{state_filters_text_for(:closed, @project)} - - else - %li{class: ("active" if params[:state] == 'closed')} - = link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do - #{state_filters_text_for(:closed, @project)} - - %li{class: ("active" if params[:state] == 'all')} - = link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do - #{state_filters_text_for(:all, @project)} - - .issues-details-filters.gray-content-block + .issues-details-filters.gray-content-block.second-block = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name]), method: :get, class: 'filter-form' do - if controller.controller_name == 'issues' && can?(current_user, :admin_issue, @project) .check-all-holder diff --git a/app/views/shared/issuable/_nav.html.haml b/app/views/shared/issuable/_nav.html.haml new file mode 100644 index 00000000000..a6970b7eebb --- /dev/null +++ b/app/views/shared/issuable/_nav.html.haml @@ -0,0 +1,25 @@ +%ul.nav-links.issues-state-filters + - if defined?(type) && type == :merge_requests + - page_context_word = 'merge requests' + - else + - page_context_word = 'issues' + %li{class: ("active" if params[:state] == 'opened')} + = link_to page_filter_path(state: 'opened'), title: "Filter by #{page_context_word} that are currently opened." do + #{state_filters_text_for(:opened, @project)} + + - if defined?(type) && type == :merge_requests + %li{class: ("active" if params[:state] == 'merged')} + = link_to page_filter_path(state: 'merged'), title: 'Filter by merge requests that are currently merged.' do + #{state_filters_text_for(:merged, @project)} + + %li{class: ("active" if params[:state] == 'closed')} + = link_to page_filter_path(state: 'closed'), title: 'Filter by merge requests that are currently closed and unmerged.' do + #{state_filters_text_for(:closed, @project)} + - else + %li{class: ("active" if params[:state] == 'closed')} + = link_to page_filter_path(state: 'closed'), title: 'Filter by issues that are currently closed.' do + #{state_filters_text_for(:closed, @project)} + + %li{class: ("active" if params[:state] == 'all')} + = link_to page_filter_path(state: 'all'), title: "Show all #{page_context_word}." do + #{state_filters_text_for(:all, @project)} diff --git a/app/views/shared/issuable/_participants.html.haml b/app/views/shared/issuable/_participants.html.haml index da6bacbb74a..ea61935487c 100644 --- a/app/views/shared/issuable/_participants.html.haml +++ b/app/views/shared/issuable/_participants.html.haml @@ -1,4 +1,8 @@ .block.participants + .sidebar-collapsed-icon + = icon('users') + %span + = participants.count .title = pluralize participants.count, "participant" - participants.each do |participant| diff --git a/app/views/shared/issuable/_search_form.html.haml b/app/views/shared/issuable/_search_form.html.haml index 6672ea79629..afad48499b7 100644 --- a/app/views/shared/issuable/_search_form.html.haml +++ b/app/views/shared/issuable/_search_form.html.haml @@ -1,9 +1,8 @@ -= form_tag(path, method: :get, id: "issue_search_form", class: 'pull-left issue-search-form') do - .append-right-10.hidden-xs.hidden-sm - = search_field_tag :issue_search, params[:issue_search], { placeholder: 'Filter by name ...', class: 'form-control issue_search search-text-input', 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'] += 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 } + = 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'] diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 3092ff54242..75a7d9be2c1 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,88 +1,132 @@ -.issuable-sidebar.issuable-affix - = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| - .block.assignee - .title - %label - Assignee - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - .pull-right - = link_to 'Edit', '#', class: 'edit-link' - .value - - if issuable.assignee - %strong= link_to_member(@project, issuable.assignee, size: 24) - - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) - %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} - = icon('exclamation-triangle') +%aside.right-sidebar{ class: sidebar_gutter_collapsed_class } + .issuable-sidebar + .block + %span.issuable-count.pull-left + = issuable.iid + of + = issuable_count(:all, @project) + %span.pull-right + %a.gutter-toggle{href: '#'} + - if sidebar_gutter_collapsed? + = icon('angle-double-left') + - else + = icon('angle-double-right') + .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} + - if has_prev_issuable?(@project, issuable.id) + = link_to 'Prev', issuable_link_prev(@project, issuable), class: 'btn btn-default' - else - .light None + %a.btn.btn-default.disabled{href: '#'} + Prev + - if has_next_issuable?(@project, issuable.id) + = link_to 'Next', issuable_link_next(@project, issuable), class: 'btn btn-default' + - else + %a.btn.btn-default.disabled{href: '#'} + Next - .selectbox - = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) + = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| + .block.assignee + .sidebar-collapsed-icon + - if issuable.assignee + = link_to_member_avatar(issuable.assignee, size: 24) + - else + = icon('user') + .title + %label + Assignee + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value + - if issuable.assignee + %strong= link_to_member(@project, issuable.assignee, size: 24) + - if issuable.instance_of?(MergeRequest) && !issuable.can_be_merged_by?(issuable.assignee) + %a.pull-right.cannot-be-merged{href: '#', data: {toggle: 'tooltip'}, title: 'Not allowed to merge'} + = icon('exclamation-triangle') + - else + .light None - .block.milestone - .title - %label - Milestone - - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - .pull-right - = link_to 'Edit', '#', class: 'edit-link' - .value - - if issuable.milestone - %span.back-to-milestone - = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do - %strong - = icon('clock-o') - = issuable.milestone.title - - else - .light None - .selectbox - = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) - = hidden_field_tag :issuable_context - = f.submit class: 'btn hide' + .selectbox + = users_select_tag("#{issuable.class.table_name.singularize}[assignee_id]", placeholder: 'Select assignee', class: 'custom-form-control js-select2 js-assignee', selected: issuable.assignee_id, project: @target_project, null_user: true, current_user: true, first_user: true) - - if issuable.project.labels.any? - .block + .block.milestone + .sidebar-collapsed-icon + = icon('balance-scale') + %span + - if issuable.milestone + = issuable.milestone.title + - else + No .title - %label Labels + %label + Milestone - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) .pull-right = link_to 'Edit', '#', class: 'edit-link' - .value.issuable-show-labels - - if issuable.labels.any? - - issuable.labels.each do |label| - = link_to_label(label) + .value + - if issuable.milestone + %span.back-to-milestone + = link_to namespace_project_milestone_path(@project.namespace, @project, issuable.milestone) do + %strong + = icon('clock-o') + = issuable.milestone.title - else .light None .selectbox - = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, - { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } + = f.select(:milestone_id, milestone_options(issuable), { include_blank: true }, { class: 'select2 select2-compact js-select2 js-milestone', data: { placeholder: 'Select milestone' }}) + = hidden_field_tag :issuable_context + = f.submit class: 'btn hide' - = render "shared/issuable/participants", participants: issuable.participants(current_user) + - if issuable.project.labels.any? + .block.labels + .sidebar-collapsed-icon + = icon('tags') + %span + = issuable.labels.count + .title + %label Labels + - if can?(current_user, :"admin_#{issuable.to_ability_name}", @project) + .pull-right + = link_to 'Edit', '#', class: 'edit-link' + .value.issuable-show-labels + - if issuable.labels.any? + - issuable.labels.each do |label| + = link_to_label(label, type: issuable.to_ability_name) + - else + .light None + .selectbox + = f.collection_select :label_ids, issuable.project.labels.all, :id, :name, + { selected: issuable.label_ids }, multiple: true, class: 'select2 js-select2', data: { placeholder: "Select labels" } - - if current_user - - subscribed = issuable.subscribed?(current_user) - .block.light - .title - %label.light Notifications - - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' - %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} - %span= subscribed ? 'Unsubscribe' : 'Subscribe' - .subscription-status{data: {status: subscribtion_status}} - .unsubscribed{class: ( 'hidden' if subscribed )} - You're not receiving notifications from this thread. - .subscribed{class: ( 'hidden' unless subscribed )} - You're receiving notifications because you're subscribed to this thread. + = render "shared/issuable/participants", participants: issuable.participants(current_user) + %hr + - if current_user + - subscribed = issuable.subscribed?(current_user) + .block.light + .sidebar-collapsed-icon + = icon('rss') + .title + %label.light Notifications + - subscribtion_status = subscribed ? 'subscribed' : 'unsubscribed' + %button.btn.btn-block.btn-gray.subscribe-button{:type => 'button'} + %span= subscribed ? 'Unsubscribe' : 'Subscribe' + .subscription-status{data: {status: subscribtion_status}} + .unsubscribed{class: ( 'hidden' if subscribed )} + You're not receiving notifications from this thread. + .subscribed{class: ( 'hidden' unless subscribed )} + You're receiving notifications because you're subscribed to this thread. - - project_ref = cross_project_reference(@project, issuable) - .block - .title - .cross-project-reference - %span - Reference: - %cite{title: project_ref} - = project_ref - = clipboard_button(clipboard_text: project_ref) + - project_ref = cross_project_reference(@project, issuable) + .block.project-reference + .sidebar-collapsed-icon + = icon('clipboard') + .title + .cross-project-reference + %span + Reference: + %cite{title: project_ref} + = project_ref + = clipboard_button(clipboard_text: project_ref) - :javascript - new Subscription("#{toggle_subscription_path(issuable)}"); - new IssuableContext();
\ No newline at end of file + :javascript + new Subscription("#{toggle_subscription_path(issuable)}"); + new IssuableContext(); diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml index e196fc51d2d..00bf9dcd2d5 100644 --- a/app/views/shared/projects/_project.html.haml +++ b/app/views/shared/projects/_project.html.haml @@ -16,9 +16,9 @@ - if avatar .dash-project-avatar - if use_creator_avatar - = image_tag avatar_icon(project.creator.email, 46), class: "avatar s46", alt:'' + = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' - else - = project_icon(project, alt: '', class: 'avatar project-avatar s46') + = project_icon(project, alt: '', class: 'avatar project-avatar s40') %span.project-full-name %span.namespace-name - if project.namespace && !skip_namespace diff --git a/doc/api/deploy_key_multiple_projects.md b/doc/api/deploy_key_multiple_projects.md index 1a5a458905e..3ad836f51b5 100644 --- a/doc/api/deploy_key_multiple_projects.md +++ b/doc/api/deploy_key_multiple_projects.md @@ -1,25 +1,29 @@ # Adding deploy keys to multiple projects -If you want to easily add the same deploy key to multiple projects in the same group, this can be achieved quite easily with the API. +If you want to easily add the same deploy key to multiple projects in the same +group, this can be achieved quite easily with the API. -First, find the ID of the projects you're interested in, by either listing all projects: +First, find the ID of the projects you're interested in, by either listing all +projects: ``` -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/projects ``` -Or finding the id of a group and then listing all projects in that group: +Or finding the ID of a group and then listing all projects in that group: ``` -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups # For group 1234: -curl --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/groups/1234 +curl -H 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' https://gitlab.example.com/api/v3/groups/1234 ``` With those IDs, add the same deploy key to all: + ``` for project_id in 321 456 987; do - curl -X POST --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' --header 'PRIVATE-TOKEN: abcdef' https://gitlab.com/api/v3/projects/${project_id}/keys + curl -X POST -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" -H "Content-Type: application/json" \ + --data '{"title": "my key", "key": "ssh-rsa AAAA..."}' https://gitlab.example.com/api/v3/projects/${project_id}/keys done ``` diff --git a/doc/api/session.md b/doc/api/session.md index 47c1c8a7a49..71e93d0bb0a 100644 --- a/doc/api/session.md +++ b/doc/api/session.md @@ -1,39 +1,47 @@ # Session -Login to get private token +You can login with both GitLab and LDAP credentials in order to obtain the +private token. ``` POST /session ``` -Parameters: +| Attribute | Type | Required | Description | +| ---------- | ------- | -------- | -------- | +| `login` | string | yes | The username of the user| +| `email` | string | yes if login is not provided | The email of the user | +| `password` | string | yes | The password of the user | -- `login` (required) - The login of user -- `email` (required if login missing) - The email of user -- `password` (required) - Valid password - -**You can login with both GitLab and LDAP credentials now** +```bash +curl -X POST "https://gitlab.example.com/api/v3/session?login=john_smith&password=strongpassw0rd" +``` +Example response: ```json { - "id": 1, - "username": "john_smith", - "email": "john@example.com", "name": "John Smith", - "private_token": "dd34asd13as", - "blocked": false, - "created_at": "2012-05-23T08:00:58Z", + "username": "john_smith", + "id": 32, + "state": "active", + "avatar_url": null, + "created_at": "2015-01-29T21:07:19.440Z", + "is_admin": true, "bio": null, "skype": "", "linkedin": "", "twitter": "", "website_url": "", - "dark_scheme": false, + "email": "john@example.com", "theme_id": 1, - "is_admin": false, + "color_scheme_id": 1, + "projects_limit": 10, + "current_sign_in_at": "2015-07-07T07:10:58.392Z", + "identities": [], "can_create_group": true, - "can_create_team": true, - "can_create_project": true + "can_create_project": true, + "two_factor_enabled": false, + "private_token": "9koXpg98eAheJpvBs5tK" } ``` diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index b955d0b0c46..2e9851fb442 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -18,7 +18,7 @@ describe 'Admin Builds' do visit admin_builds_path - expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') + expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page.all('.build-link').size).to eq(4) expect(page).to have_link 'Cancel all' end @@ -28,7 +28,7 @@ describe 'Admin Builds' do it 'shows a message' do visit admin_builds_path - expect(page).to have_selector('.project-issuable-filter li.active', text: 'All') + expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content 'No builds to show' expect(page).not_to have_link 'Cancel all' end @@ -44,7 +44,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :running) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') + expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page.find('.build-link')).to have_content(build1.id) expect(page.find('.build-link')).not_to have_content(build2.id) expect(page.find('.build-link')).not_to have_content(build3.id) @@ -58,7 +58,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :running) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Running') + expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page).to have_content 'No builds to show' expect(page).not_to have_link 'Cancel all' end @@ -74,7 +74,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :finished) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') + expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page.find('.build-link')).not_to have_content(build1.id) expect(page.find('.build-link')).not_to have_content(build2.id) expect(page.find('.build-link')).to have_content(build3.id) @@ -88,7 +88,7 @@ describe 'Admin Builds' do visit admin_builds_path(scope: :finished) - expect(page).to have_selector('.project-issuable-filter li.active', text: 'Finished') + expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page).to have_content 'No builds to show' expect(page).to have_link 'Cancel all' end diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb index 0b9176357bc..4f129eca183 100644 --- a/spec/helpers/labels_helper_spec.rb +++ b/spec/helpers/labels_helper_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe LabelsHelper do describe 'link_to_label' do let(:project) { create(:empty_project) } - let(:label) { create(:label, project: project) } + let(:label) { create(:label, project: project) } context 'with @project set' do before do @@ -11,34 +11,31 @@ describe LabelsHelper do end it 'uses the instance variable' do - expect(label).not_to receive(:project) - link_to_label(label) + expect(link_to_label(label)).to match %r{<a href="/#{@project.to_reference}/issues\?label_name=#{label.name}">.*</a>} end end context 'without @project set' do it "uses the label's project" do - expect(label).to receive(:project).and_return(project) - link_to_label(label) + expect(link_to_label(label)).to match %r{<a href="/#{label.project.to_reference}/issues\?label_name=#{label.name}">.*</a>} end end - context 'with a named project argument' do - it 'uses the provided project' do - arg = double('project') - expect(arg).to receive(:namespace).and_return('foo') - expect(arg).to receive(:to_param).and_return('foo') + context 'with a project argument' do + let(:another_project) { double('project', namespace: 'foo3', to_param: 'bar3') } - link_to_label(label, project: arg) + it 'links to merge requests page' do + expect(link_to_label(label, project: another_project)).to match %r{<a href="/foo3/bar3/issues\?label_name=#{label.name}">.*</a>} end + end - it 'takes precedence over other types' do - @project = project - expect(@project).not_to receive(:namespace) - expect(label).not_to receive(:project) - - arg = double('project', namespace: 'foo', to_param: 'foo') - link_to_label(label, project: arg) + context 'with a type argument' do + ['issue', :issue, 'merge_request', :merge_request].each do |type| + context "set to #{type}" do + it 'links to correct page' do + expect(link_to_label(label, type: type)).to match %r{<a href="/#{label.project.to_reference}/#{type.to_s.pluralize}\?label_name=#{label.name}">.*</a>} + end + end end end |