Commit 004f3a0b authored by Sam Rose's avatar Sam Rose

Activate group name toggle based on horizontal space

parent 57f79da9
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;
&.initializing {
display: none;
&.wrap {
white-space: normal;
}
@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;
&.initializing {
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'
......
- 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,32 +6,40 @@ 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')
it 'is not present if enough horizontal space' do
visit group_path(nested_group_3)
visit group_path(nested_group_1)
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
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 present if the title is longer than the container' do
visit group_path(nested_group_3)
expect(page).to have_css('.group-name-toggle')
end
title_width = page.evaluate_script("$('.title')[0].offsetWidth")
context 'for group with at least 3 groups' do
before do
visit group_path(nested_group_2)
page_height = page.current_window.size[1]
page.current_window.resize_to(SMALL_SCREEN, page_height)
find('.group-name-toggle')
container_width = page.evaluate_script("$('.title-container')[0].offsetWidth")
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)
......@@ -40,5 +48,4 @@ feature 'Group name toggle', feature: true, js: true do
expect(page).to have_content(group.name)
expect(page).to have_css('.group-path.hidable', visible: true)
end
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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment