New navigation breadcrumbs
This commit is contained in:
parent
a6c02ce6b9
commit
ec396fd93a
19 changed files with 232 additions and 36 deletions
|
@ -1,13 +1,13 @@
|
|||
|
||||
import Cookies from 'js-cookie';
|
||||
import _ from 'underscore';
|
||||
|
||||
export default class GroupName {
|
||||
constructor() {
|
||||
this.titleContainer = document.querySelector('.title-container');
|
||||
this.title = document.querySelector('.title');
|
||||
this.titleContainer = document.querySelector('.js-title-container');
|
||||
this.title = this.titleContainer.querySelector('.title');
|
||||
this.titleWidth = this.title.offsetWidth;
|
||||
this.groupTitle = document.querySelector('.group-title');
|
||||
this.groups = document.querySelectorAll('.group-path');
|
||||
this.groupTitle = this.titleContainer.querySelector('.group-title');
|
||||
this.groups = this.titleContainer.querySelectorAll('.group-path');
|
||||
this.toggle = null;
|
||||
this.isHidden = false;
|
||||
this.init();
|
||||
|
@ -33,11 +33,20 @@ export default class GroupName {
|
|||
|
||||
createToggle() {
|
||||
this.toggle = document.createElement('button');
|
||||
this.toggle.setAttribute('type', 'button');
|
||||
this.toggle.className = 'text-expander group-name-toggle';
|
||||
this.toggle.setAttribute('aria-label', 'Toggle full path');
|
||||
this.toggle.innerHTML = '...';
|
||||
if (Cookies.get('new_nav') === 'true') {
|
||||
this.toggle.innerHTML = '<i class="fa fa-ellipsis-h" aria-hidden="true"></i>';
|
||||
} else {
|
||||
this.toggle.innerHTML = '...';
|
||||
}
|
||||
this.toggle.addEventListener('click', this.toggleGroups.bind(this));
|
||||
this.titleContainer.insertBefore(this.toggle, this.title);
|
||||
if (Cookies.get('new_nav') === 'true') {
|
||||
this.title.insertBefore(this.toggle, this.groupTitle);
|
||||
} else {
|
||||
this.titleContainer.insertBefore(this.toggle, this.title);
|
||||
}
|
||||
this.toggleGroups();
|
||||
}
|
||||
|
||||
|
|
|
@ -264,3 +264,127 @@ header.navbar-gitlab-new {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
min-height: 60px;
|
||||
padding-top: $gl-padding-top;
|
||||
padding-bottom: $gl-padding-top;
|
||||
color: $gl-text-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.dropdown-toggle-caret {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
padding: 0 5px;
|
||||
color: rgba($black, .65);
|
||||
font-size: 10px;
|
||||
line-height: 1;
|
||||
background: none;
|
||||
border: 0;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.dropdown-menu-projects {
|
||||
margin-top: -$gl-padding;
|
||||
margin-left: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs-links {
|
||||
flex: 1;
|
||||
align-self: center;
|
||||
color: $black-transparent;
|
||||
|
||||
a {
|
||||
color: rgba($black, .65);
|
||||
|
||||
&:not(:first-child),
|
||||
&.group-path {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
&:not(:last-of-type),
|
||||
&.group-path {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
|
||||
> a {
|
||||
&:last-of-type {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-tile {
|
||||
margin-right: 5px;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 50%;
|
||||
vertical-align: sub;
|
||||
|
||||
&.identicon {
|
||||
float: left;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-top: 2px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.text-expander {
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
|
||||
> i {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumbs-extra {
|
||||
flex: 0 0 auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.breadcrumbs-sub-title {
|
||||
margin: 2px 0 0;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
|
||||
&:not(:last-child) {
|
||||
&::after {
|
||||
content: "/";
|
||||
margin: 0 2px 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child a {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@ module GroupsHelper
|
|||
full_title = ''
|
||||
|
||||
group.ancestors.reverse.each do |parent|
|
||||
full_title += link_to(simple_sanitize(parent.name), group_path(parent), class: 'group-path hidable')
|
||||
full_title += group_title_link(parent, hidable: true)
|
||||
|
||||
full_title += '<span class="hidable"> / </span>'.html_safe
|
||||
end
|
||||
|
||||
full_title += link_to(simple_sanitize(group.name), group_path(group), class: 'group-path')
|
||||
full_title += group_title_link(group)
|
||||
full_title += ' · '.html_safe + link_to(simple_sanitize(name), url, class: 'group-path') if name
|
||||
|
||||
content_tag :span, class: 'group-title' do
|
||||
|
@ -56,4 +57,20 @@ module GroupsHelper
|
|||
def group_issues(group)
|
||||
IssuesFinder.new(current_user, group_id: group.id).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def group_title_link(group, hidable: false)
|
||||
link_to(group_path(group), class: "group-path #{'hidable' if hidable}") do
|
||||
output =
|
||||
if show_new_nav?
|
||||
image_tag(group_icon(group), class: "avatar-tile", width: 16, height: 16)
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
output << simple_sanitize(group.name)
|
||||
output.html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,7 +58,17 @@ module ProjectsHelper
|
|||
link_to(simple_sanitize(owner.name), user_path(owner))
|
||||
end
|
||||
|
||||
project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" }
|
||||
project_link = link_to project_path(project), { class: "project-item-select-holder" } do
|
||||
output =
|
||||
if show_new_nav?
|
||||
project_icon(project, alt: project.name, class: 'avatar-tile', width: 16, height: 16)
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
output << simple_sanitize(project.name)
|
||||
output.html_safe
|
||||
end
|
||||
|
||||
if current_user
|
||||
project_link << button_tag(type: 'button', class: 'dropdown-toggle-caret js-projects-dropdown-toggle', aria: { label: 'Toggle switch project dropdown' }, data: { target: '.js-dropdown-menu-projects', toggle: 'dropdown', order_by: 'last_activity_at' }) do
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- @no_container = true
|
||||
|
||||
= content_for :meta_tags do
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Groups"
|
||||
- header_title "Groups", dashboard_groups_path
|
||||
= render 'dashboard/groups_head'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title 'Milestones'
|
||||
- header_title 'Milestones', dashboard_milestones_path
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
- @no_container = true
|
||||
- @hide_top_links = true
|
||||
- @breadcrumb_title = "Projects"
|
||||
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Snippets"
|
||||
- header_title "Snippets", dashboard_snippets_path
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
= render "layouts/broadcast"
|
||||
= render "layouts/flash"
|
||||
= yield :flash_message
|
||||
- if show_new_nav?
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
|
||||
.content{ id: "content-body" }
|
||||
= yield
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
= link_to root_path, class: 'home', title: 'Dashboard', id: 'logo' do
|
||||
= brand_header_logo
|
||||
|
||||
.title-container
|
||||
.title-container.js-title-container
|
||||
%h1.title{ class: ('initializing' if @has_group_title) }= title
|
||||
|
||||
.navbar-collapse.collapse
|
||||
|
|
|
@ -83,8 +83,6 @@
|
|||
= icon('ellipsis-v', class: 'js-navbar-toggle-right')
|
||||
= icon('times', class: 'js-navbar-toggle-left', style: 'display: none;')
|
||||
|
||||
= yield :header_content
|
||||
|
||||
= render 'shared/outdated_browser'
|
||||
|
||||
- if @project && !@project.empty_repo?
|
||||
|
|
19
app/views/layouts/nav/_breadcrumbs.html.haml
Normal file
19
app/views/layouts/nav/_breadcrumbs.html.haml
Normal file
|
@ -0,0 +1,19 @@
|
|||
- breadcrumb_title = @breadcrumb_title || controller.controller_name.humanize
|
||||
- hide_top_links = @hide_top_links || false
|
||||
|
||||
%nav.breadcrumbs{ role: "navigation" }
|
||||
.breadcrumbs-container{ class: container_class }
|
||||
.breadcrumbs-links.js-title-container
|
||||
- unless hide_top_links
|
||||
.title
|
||||
= link_to "GitLab", root_path
|
||||
\/
|
||||
= header_title
|
||||
%h2.breadcrumbs-sub-title
|
||||
%ul.list-unstyled
|
||||
- if content_for?(:sub_title_before)
|
||||
= yield :sub_title_before
|
||||
%li= link_to breadcrumb_title, request.path
|
||||
- if content_for?(:breadcrumbs_extra)
|
||||
.breadcrumbs-extra.hidden-xs= yield :breadcrumbs_extra
|
||||
= yield :header_content
|
|
@ -2,6 +2,10 @@
|
|||
- @content_class = "issue-boards-content"
|
||||
- page_title "Boards"
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :sub_title_before do
|
||||
%li= link_to "Issues", namespace_project_issues_path(@project.namespace, @project)
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
= webpack_bundle_tag 'common_vue'
|
||||
= webpack_bundle_tag 'filtered_search'
|
||||
|
|
11
app/views/projects/issues/_nav_btns.html.haml
Normal file
11
app/views/projects/issues/_nav_btns.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
|||
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10 has-tooltip', title: 'Subscribe' do
|
||||
= icon('rss')
|
||||
- if @can_bulk_update
|
||||
= button_tag "Edit Issues", class: "btn btn-default append-right-10 js-bulk-update-toggle"
|
||||
= link_to "New issue", new_namespace_project_issue_path(@project.namespace,
|
||||
@project,
|
||||
issue: { assignee_id: issues_finder.assignee.try(:id),
|
||||
milestone_id: issues_finder.milestones.first.try(:id) }),
|
||||
class: "btn btn-new",
|
||||
title: "New issue",
|
||||
id: "new_issue_link"
|
|
@ -13,23 +13,16 @@
|
|||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues")
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= render "projects/issues/nav_btns"
|
||||
|
||||
- if project_issues(@project).exists?
|
||||
%div{ class: (container_class) }
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :issues
|
||||
.nav-controls
|
||||
= link_to params.merge(rss_url_options), class: 'btn append-right-10 has-tooltip', title: 'Subscribe' do
|
||||
= icon('rss')
|
||||
- if @can_bulk_update
|
||||
= button_tag "Edit Issues", class: "btn btn-default js-bulk-update-toggle"
|
||||
= link_to new_namespace_project_issue_path(@project.namespace,
|
||||
@project,
|
||||
issue: { assignee_id: issues_finder.assignee.try(:id),
|
||||
milestone_id: issues_finder.milestones.first.try(:id) }),
|
||||
class: "btn btn-new",
|
||||
title: "New issue",
|
||||
id: "new_issue_link" do
|
||||
New issue
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= render "projects/issues/nav_btns"
|
||||
= render 'shared/issuable/search_bar', type: :issues
|
||||
|
||||
- if @can_bulk_update
|
||||
|
|
5
app/views/projects/merge_requests/_nav_btns.html.haml
Normal file
5
app/views/projects/merge_requests/_nav_btns.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
- if @can_bulk_update
|
||||
= button_tag "Edit Merge Requests", class: "btn js-bulk-update-toggle"
|
||||
- if merge_project
|
||||
= link_to new_merge_request_path, class: "btn btn-new", title: "New merge request" do
|
||||
New merge request
|
|
@ -1,5 +1,7 @@
|
|||
- @no_container = true
|
||||
- @can_bulk_update = can?(current_user, :admin_merge_request, @project)
|
||||
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
|
||||
- new_merge_request_path = namespace_project_new_merge_request_path(merge_project.namespace, merge_project) if merge_project
|
||||
|
||||
- page_title "Merge Requests"
|
||||
- unless @project.default_issues_tracker?
|
||||
|
@ -10,22 +12,18 @@
|
|||
= webpack_bundle_tag 'common_vue'
|
||||
= webpack_bundle_tag 'filtered_search'
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= render "projects/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path
|
||||
|
||||
= render 'projects/last_push'
|
||||
|
||||
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
|
||||
- new_merge_request_path = namespace_project_new_merge_request_path(merge_project.namespace, merge_project) if merge_project
|
||||
|
||||
- if @project.merge_requests.exists?
|
||||
%div{ class: container_class }
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :merge_requests
|
||||
.nav-controls
|
||||
- if @can_bulk_update
|
||||
= button_tag "Edit Merge Requests", class: "btn js-bulk-update-toggle"
|
||||
- if merge_project
|
||||
= link_to new_merge_request_path, class: "btn btn-new", title: "New merge request" do
|
||||
New merge request
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= render "projects/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path
|
||||
|
||||
= render 'shared/issuable/search_bar', type: :merge_requests
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ describe GroupsHelper do
|
|||
let!(:very_deep_nested_group) { create(:group, parent: deep_nested_group) }
|
||||
|
||||
it 'outputs the groups in the correct order' do
|
||||
expect(group_title(very_deep_nested_group)).to match(/>#{group.name}<\/a>.*>#{nested_group.name}<\/a>.*>#{deep_nested_group.name}<\/a>/)
|
||||
expect(helper.group_title(very_deep_nested_group)).to match(/>#{group.name}<\/a>.*>#{nested_group.name}<\/a>.*>#{deep_nested_group.name}<\/a>/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue