diff --git a/app/assets/javascripts/issuable_context.js.coffee b/app/assets/javascripts/issuable_context.js.coffee index 02232698bc2..c2144aea25e 100644 --- a/app/assets/javascripts/issuable_context.js.coffee +++ b/app/assets/javascripts/issuable_context.js.coffee @@ -10,18 +10,6 @@ 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) -> block = $(@).parents('.block') block.find('.selectbox').show() diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 540d0b03163..e0fc969ff0e 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -200,6 +200,10 @@ } } +@mixin expanded-gutter { + padding-right: $gutter_width; +} + @mixin collapsed-sidebar { padding-left: $sidebar_collapsed_width; @@ -266,6 +270,7 @@ background: #f2f6f7; } +// page is small enough @media (max-width: $screen-md-max) { .page-sidebar-collapsed { @include collapsed-sidebar; @@ -280,7 +285,13 @@ } } +// page is large enough @media(min-width: $screen-md-max) { + + .page-gutter { + @include expanded-gutter; + } + .page-sidebar-collapsed { @include collapsed-sidebar; } @@ -288,4 +299,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..7af6688963f 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -12,6 +12,8 @@ $gl-font-size: 15px; $list-font-size: 15px; $sidebar_collapsed_width: 62px; $sidebar_width: 230px; +$gutter_collapsed_width: 62px; +$gutter_width: 320px; $avatar_radius: 50%; $code_font_size: 13px; $code_line_height: 1.5; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 977ada0ff38..d1f2175bfb7 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -133,3 +133,16 @@ margin-right: 2px; } } + + +.right-sidebar { + position: fixed; + top: 58px; + right: 0; + height: 100%; + transition-duration: .3s; + background: $gray-light; + overflow: scroll; + width: $gutter_width; + padding: 10px 20px; +} \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a2458ad3be0..57a9ce8294a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -293,6 +293,36 @@ module ApplicationHelper 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) + 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 prev_issuable_for(project) + 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 state_filters_text_for(entity, project) titles = { opened: "Open" diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index e6fb8670e57..20b89cc9db3 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -19,6 +19,12 @@ module NavHelper end end + def page_gutter_class + if current_path?('merge_requests#show') || current_path?('issues#show') + "page-gutter" + end + end + def nav_header_class if nav_menu_collapsed? "header-collapsed" 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/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 51dcca7a1ab..a567c22c823 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -54,11 +54,9 @@ = 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/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 8641c3d8b4b..c2ecb48b094 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -70,11 +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 @@ -87,6 +85,8 @@ .mr-loading-status = spinner += render 'shared/issuable/sidebar', issuable: @merge_request + :javascript var merge_request; diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 3092ff54242..2aa6dc840eb 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -1,88 +1,98 @@ -.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') - - else - .light None - - .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) - - .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' - - - if issuable.project.labels.any? - .block +%aside.right-sidebar + .issuable-sidebar + .block + = issuable.iid + of + = issuable_count(:all, @project) + .issuable-nav.pull-right.btn-group{role: 'group', "aria-label" => '...'} + %a.btn.btn-default{href: '#'} + Prev + %a.btn.btn-default{href: '#'} + Next + = 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 Labels + %label + Assignee - 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.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 + + .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) + + .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.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 + .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) + - 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 + = render "shared/issuable/participants", participants: issuable.participants(current_user) + + - 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. + + - project_ref = cross_project_reference(@project, issuable) + .block .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. + .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 - .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(); \ No newline at end of file