Merge branch '28187-project-name-cut-off-with-nested-groups' into 'master'
Resolve "Project name cut off with nested groups" Closes #28187 and #28179 See merge request !10065
This commit is contained in:
commit
b46ac16cc8
8 changed files with 110 additions and 73 deletions
|
@ -1,40 +1,64 @@
|
|||
const GROUP_LIMIT = 2;
|
||||
|
||||
import _ from 'underscore';
|
||||
|
||||
export default class GroupName {
|
||||
constructor() {
|
||||
this.titleContainer = document.querySelector('.title');
|
||||
this.groups = document.querySelectorAll('.group-path');
|
||||
this.titleContainer = document.querySelector('.title-container');
|
||||
this.title = document.querySelector('.title');
|
||||
this.titleWidth = this.title.offsetWidth;
|
||||
this.groupTitle = document.querySelector('.group-title');
|
||||
this.groups = document.querySelectorAll('.group-path');
|
||||
this.toggle = null;
|
||||
this.isHidden = false;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
if (this.groups.length > GROUP_LIMIT) {
|
||||
if (this.groups.length > 0) {
|
||||
this.groups[this.groups.length - 1].classList.remove('hidable');
|
||||
this.addToggle();
|
||||
this.toggleHandler();
|
||||
window.addEventListener('resize', _.debounce(this.toggleHandler.bind(this), 100));
|
||||
}
|
||||
this.render();
|
||||
}
|
||||
|
||||
addToggle() {
|
||||
const header = document.querySelector('.header-content');
|
||||
toggleHandler() {
|
||||
if (this.titleWidth > this.titleContainer.offsetWidth) {
|
||||
if (!this.toggle) this.createToggle();
|
||||
this.showToggle();
|
||||
} else if (this.toggle) {
|
||||
this.hideToggle();
|
||||
}
|
||||
}
|
||||
|
||||
createToggle() {
|
||||
this.toggle = document.createElement('button');
|
||||
this.toggle.className = 'text-expander group-name-toggle';
|
||||
this.toggle.setAttribute('aria-label', 'Toggle full path');
|
||||
this.toggle.innerHTML = '...';
|
||||
this.toggle.addEventListener('click', this.toggleGroups.bind(this));
|
||||
header.insertBefore(this.toggle, this.titleContainer);
|
||||
this.titleContainer.insertBefore(this.toggle, this.title);
|
||||
this.toggleGroups();
|
||||
}
|
||||
|
||||
showToggle() {
|
||||
this.title.classList.add('wrap');
|
||||
this.toggle.classList.remove('hidden');
|
||||
if (this.isHidden) this.groupTitle.classList.add('is-hidden');
|
||||
}
|
||||
|
||||
hideToggle() {
|
||||
this.title.classList.remove('wrap');
|
||||
this.toggle.classList.add('hidden');
|
||||
if (this.isHidden) this.groupTitle.classList.remove('is-hidden');
|
||||
}
|
||||
|
||||
toggleGroups() {
|
||||
this.isHidden = !this.isHidden;
|
||||
this.groupTitle.classList.toggle('is-hidden');
|
||||
}
|
||||
|
||||
render() {
|
||||
this.titleContainer.classList.remove('initializing');
|
||||
this.title.classList.remove('initializing');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ header {
|
|||
padding: 0 16px;
|
||||
z-index: 100;
|
||||
margin-bottom: 0;
|
||||
height: $header-height;
|
||||
min-height: $header-height;
|
||||
background-color: $gray-light;
|
||||
border: none;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
@ -85,7 +85,7 @@ header {
|
|||
|
||||
.navbar-toggle {
|
||||
color: $nav-toggle-gray;
|
||||
margin: 6px 0;
|
||||
margin: 7px 0;
|
||||
border-radius: 0;
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
|
@ -135,12 +135,14 @@ header {
|
|||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
height: $header-height;
|
||||
min-height: $header-height;
|
||||
padding-left: 30px;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
padding-right: 0;
|
||||
@media (max-width: $screen-sm-max) {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
|
@ -165,8 +167,7 @@ header {
|
|||
}
|
||||
|
||||
.group-name-toggle {
|
||||
margin: 0 5px;
|
||||
vertical-align: sub;
|
||||
margin: 3px 5px;
|
||||
}
|
||||
|
||||
.group-title {
|
||||
|
@ -177,39 +178,32 @@ header {
|
|||
}
|
||||
}
|
||||
|
||||
.title-container {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex: 1 1 auto;
|
||||
padding-top: (($header-height - 19) / 2);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
padding-right: 20px;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
max-width: 385px;
|
||||
line-height: 22px;
|
||||
display: inline-block;
|
||||
line-height: $header-height;
|
||||
font-weight: normal;
|
||||
color: $gl-text-color;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: top;
|
||||
white-space: nowrap;
|
||||
|
||||
&.wrap {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
&.initializing {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
max-width: 190px;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-sm-min) and (max-width: $screen-md-max) {
|
||||
max-width: 428px;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-lg-min) {
|
||||
max-width: 685px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
|
@ -226,10 +220,10 @@ header {
|
|||
border: transparent;
|
||||
background: transparent;
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 3px;
|
||||
width: 12px;
|
||||
line-height: 19px;
|
||||
margin-top: (($header-height - 19) / 2);
|
||||
padding: 0;
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
|
@ -247,7 +241,7 @@ header {
|
|||
}
|
||||
|
||||
.navbar-collapse {
|
||||
float: right;
|
||||
flex: 0 0 auto;
|
||||
border-top: none;
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
|
@ -255,7 +249,7 @@ header {
|
|||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
float: none;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,9 @@
|
|||
border: 1px solid $border-gray-dark;
|
||||
border-radius: $border-radius-default;
|
||||
margin-left: 5px;
|
||||
line-height: 1;
|
||||
font-size: $gl-font-size;
|
||||
line-height: $gl-font-size;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($gray-light, 10%);
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
.group-root-path {
|
||||
max-width: 40vw;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: nowrap;
|
||||
}
|
||||
|
||||
.group-row {
|
||||
.stats {
|
||||
float: right;
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
%span.sr-only Toggle navigation
|
||||
= icon('ellipsis-v')
|
||||
|
||||
.header-logo
|
||||
= link_to root_path, class: 'home', title: 'Dashboard', id: 'logo' do
|
||||
= brand_header_logo
|
||||
|
||||
.title-container
|
||||
%h1.title{ class: ('initializing' if @has_group_title) }= title
|
||||
|
||||
.navbar-collapse.collapse
|
||||
%ul.nav.navbar-nav
|
||||
%li.hidden-sm.hidden-xs
|
||||
|
@ -63,12 +70,6 @@
|
|||
%div
|
||||
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
|
||||
|
||||
.header-logo
|
||||
= link_to root_path, class: 'home', title: 'Dashboard', id: 'logo' do
|
||||
= brand_header_logo
|
||||
|
||||
%h1.title{ class: ('initializing' if @has_group_title) }= title
|
||||
|
||||
= yield :header_content
|
||||
|
||||
= render 'shared/outdated_browser'
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
- parent = Group.find_by(id: params[:parent_id] || @group.parent_id)
|
||||
- group_path = root_url
|
||||
- group_path << parent.full_path + '/' if parent
|
||||
- if @group.persisted?
|
||||
.form-group
|
||||
= f.label :name, class: 'control-label' do
|
||||
|
@ -11,7 +13,7 @@
|
|||
Group path
|
||||
.col-sm-10
|
||||
.input-group.gl-field-error-anchor
|
||||
.input-group-addon
|
||||
.group-root-path.input-group-addon.has-tooltip{ title: group_path, :'data-placement' => 'bottom' }
|
||||
%span>= root_url
|
||||
- if parent
|
||||
%strong= parent.full_path + '/'
|
||||
|
|
|
@ -6,39 +6,46 @@ feature 'Group name toggle', feature: true, js: true do
|
|||
let(:nested_group_2) { create(:group, parent: nested_group_1) }
|
||||
let(:nested_group_3) { create(:group, parent: nested_group_2) }
|
||||
|
||||
SMALL_SCREEN = 300
|
||||
|
||||
before do
|
||||
login_as :user
|
||||
end
|
||||
|
||||
it 'is not present for less than 3 groups' do
|
||||
visit group_path(group)
|
||||
expect(page).not_to have_css('.group-name-toggle')
|
||||
|
||||
visit group_path(nested_group_1)
|
||||
expect(page).not_to have_css('.group-name-toggle')
|
||||
end
|
||||
|
||||
it 'is present for nested group of 3 or more in the namespace' do
|
||||
visit group_path(nested_group_2)
|
||||
expect(page).to have_css('.group-name-toggle')
|
||||
|
||||
it 'is not present if enough horizontal space' do
|
||||
visit group_path(nested_group_3)
|
||||
expect(page).to have_css('.group-name-toggle')
|
||||
|
||||
container_width = page.evaluate_script("$('.title-container')[0].offsetWidth")
|
||||
title_width = page.evaluate_script("$('.title')[0].offsetWidth")
|
||||
|
||||
expect(container_width).to be > title_width
|
||||
expect(page).not_to have_css('.group-name-toggle')
|
||||
end
|
||||
|
||||
context 'for group with at least 3 groups' do
|
||||
before do
|
||||
visit group_path(nested_group_2)
|
||||
end
|
||||
it 'is present if the title is longer than the container' do
|
||||
visit group_path(nested_group_3)
|
||||
title_width = page.evaluate_script("$('.title')[0].offsetWidth")
|
||||
|
||||
it 'should show the full group namespace when toggled' do
|
||||
expect(page).not_to have_content(group.name)
|
||||
expect(page).to have_css('.group-path.hidable', visible: false)
|
||||
page_height = page.current_window.size[1]
|
||||
page.current_window.resize_to(SMALL_SCREEN, page_height)
|
||||
|
||||
click_button '...'
|
||||
find('.group-name-toggle')
|
||||
container_width = page.evaluate_script("$('.title-container')[0].offsetWidth")
|
||||
|
||||
expect(page).to have_content(group.name)
|
||||
expect(page).to have_css('.group-path.hidable', visible: true)
|
||||
end
|
||||
expect(title_width).to be > container_width
|
||||
end
|
||||
|
||||
it 'should show the full group namespace when toggled' do
|
||||
page_height = page.current_window.size[1]
|
||||
page.current_window.resize_to(SMALL_SCREEN, page_height)
|
||||
visit group_path(nested_group_3)
|
||||
|
||||
expect(page).not_to have_content(group.name)
|
||||
expect(page).to have_css('.group-path.hidable', visible: false)
|
||||
|
||||
click_button '...'
|
||||
|
||||
expect(page).to have_content(group.name)
|
||||
expect(page).to have_css('.group-path.hidable', visible: true)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ feature 'toggler_behavior', js: true, feature: true do
|
|||
it 'should be scrolled down to fragment' do
|
||||
page_height = page.current_window.size[1]
|
||||
page_scroll_y = page.evaluate_script("window.scrollY")
|
||||
fragment_position_top = page.evaluate_script("$('#{fragment_id}').offset().top")
|
||||
fragment_position_top = page.evaluate_script("Math.round($('#{fragment_id}').offset().top)")
|
||||
expect(find('.js-toggle-content').visible?).to eq true
|
||||
expect(find(fragment_id).visible?).to eq true
|
||||
expect(fragment_position_top).to be >= page_scroll_y
|
||||
|
|
Loading…
Reference in a new issue