Merge branch '26200-convert-sidebar-to-dropdown' into 'master'
Resolve "Update global sidebar to dropdown" Closes #26200 See merge request !9199
This commit is contained in:
commit
aa792b91bb
|
@ -101,11 +101,6 @@ require('es6-promise').polyfill();
|
|||
}
|
||||
});
|
||||
|
||||
$('.nav-sidebar').niceScroll({
|
||||
cursoropacitymax: '0.4',
|
||||
cursorcolor: '#FFF',
|
||||
cursorborder: '1px solid #FFF'
|
||||
});
|
||||
$('.js-select-on-focus').on('focusin', function () {
|
||||
return $(this).select().one('mouseup', function (e) {
|
||||
return e.preventDefault();
|
||||
|
@ -245,8 +240,6 @@ require('es6-promise').polyfill();
|
|||
});
|
||||
gl.awardsHandler = new AwardsHandler();
|
||||
new Aside();
|
||||
// bind sidebar events
|
||||
new gl.Sidebar();
|
||||
|
||||
gl.utils.initTimeagoTimeout();
|
||||
});
|
||||
|
|
|
@ -38,13 +38,15 @@
|
|||
this.$buttons.attr('data-status', newStatus);
|
||||
this.$buttons.find('> span').text(newAction);
|
||||
|
||||
for (const button of this.$buttons) {
|
||||
this.$buttons.map((button) => {
|
||||
const $button = $(button);
|
||||
|
||||
if ($button.attr('data-original-title')) {
|
||||
$button.tooltip('hide').attr('data-original-title', newAction).tooltip('fixTitle');
|
||||
}
|
||||
}
|
||||
|
||||
return button;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,16 @@
|
|||
};
|
||||
|
||||
Sidebar.prototype.addEventListeners = function() {
|
||||
const $document = $(document);
|
||||
const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight, 10);
|
||||
|
||||
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
|
||||
$('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden);
|
||||
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
|
||||
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
|
||||
$(document).on('click', '.js-sidebar-toggle', function(e, triggered) {
|
||||
$(window).on('resize', () => throttledSetSidebarHeight());
|
||||
$document.on('scroll', () => throttledSetSidebarHeight());
|
||||
$document.on('click', '.js-sidebar-toggle', function(e, triggered) {
|
||||
var $allGutterToggleIcons, $this, $thisIcon;
|
||||
e.preventDefault();
|
||||
$this = $(this);
|
||||
|
@ -191,6 +196,17 @@
|
|||
}
|
||||
};
|
||||
|
||||
Sidebar.prototype.setSidebarHeight = function() {
|
||||
const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight();
|
||||
const $rightSidebar = $('.js-right-sidebar');
|
||||
const diff = $navHeight - $('body').scrollTop();
|
||||
if (diff > 0) {
|
||||
$rightSidebar.outerHeight($(window).height() - diff);
|
||||
} else {
|
||||
$rightSidebar.outerHeight('100%');
|
||||
}
|
||||
};
|
||||
|
||||
Sidebar.prototype.isOpen = function() {
|
||||
return this.sidebar.is('.right-sidebar-expanded');
|
||||
};
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/* eslint-disable arrow-parens, class-methods-use-this, no-param-reassign */
|
||||
/* global Cookies */
|
||||
|
||||
(() => {
|
||||
const pinnedStateCookie = 'pin_nav';
|
||||
const sidebarBreakpoint = 1024;
|
||||
|
||||
const pageSelector = '.page-with-sidebar';
|
||||
const navbarSelector = '.navbar-gitlab';
|
||||
const sidebarWrapperSelector = '.sidebar-wrapper';
|
||||
const sidebarContentSelector = '.nav-sidebar';
|
||||
|
||||
const pinnedToggleSelector = '.js-nav-pin';
|
||||
const sidebarToggleSelector = '.toggle-nav-collapse, .side-nav-toggle';
|
||||
|
||||
const pinnedPageClass = 'page-sidebar-pinned';
|
||||
const expandedPageClass = 'page-sidebar-expanded';
|
||||
|
||||
const pinnedNavbarClass = 'header-sidebar-pinned';
|
||||
const expandedNavbarClass = 'header-sidebar-expanded';
|
||||
|
||||
class Sidebar {
|
||||
constructor() {
|
||||
if (!Sidebar.singleton) {
|
||||
Sidebar.singleton = this;
|
||||
Sidebar.singleton.init();
|
||||
}
|
||||
|
||||
return Sidebar.singleton;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.isPinned = Cookies.get(pinnedStateCookie) === 'true';
|
||||
this.isExpanded = (
|
||||
window.innerWidth >= sidebarBreakpoint &&
|
||||
$(pageSelector).hasClass(expandedPageClass)
|
||||
);
|
||||
$(window).on('resize', () => this.setSidebarHeight());
|
||||
$(document)
|
||||
.on('click', sidebarToggleSelector, () => this.toggleSidebar())
|
||||
.on('click', pinnedToggleSelector, () => this.togglePinnedState())
|
||||
.on('click', 'html, body, a, button', (e) => this.handleClickEvent(e))
|
||||
.on('DOMContentLoaded', () => this.renderState())
|
||||
.on('scroll', () => this.setSidebarHeight())
|
||||
.on('todo:toggle', (e, count) => this.updateTodoCount(count));
|
||||
this.renderState();
|
||||
this.setSidebarHeight();
|
||||
}
|
||||
|
||||
handleClickEvent(e) {
|
||||
if (this.isExpanded && (!this.isPinned || window.innerWidth < sidebarBreakpoint)) {
|
||||
const $target = $(e.target);
|
||||
const targetIsToggle = $target.closest(sidebarToggleSelector).length > 0;
|
||||
const targetIsSidebar = $target.closest(sidebarWrapperSelector).length > 0;
|
||||
if (!targetIsToggle && (!targetIsSidebar || $target.closest('a'))) {
|
||||
this.toggleSidebar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateTodoCount(count) {
|
||||
$('.js-todos-count').text(gl.text.addDelimiter(count));
|
||||
}
|
||||
|
||||
toggleSidebar() {
|
||||
this.isExpanded = !this.isExpanded;
|
||||
this.renderState();
|
||||
}
|
||||
|
||||
setSidebarHeight() {
|
||||
const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight();
|
||||
const diff = $navHeight - $('body').scrollTop();
|
||||
if (diff > 0) {
|
||||
$('.js-right-sidebar').outerHeight($(window).height() - diff);
|
||||
} else {
|
||||
$('.js-right-sidebar').outerHeight('100%');
|
||||
}
|
||||
}
|
||||
|
||||
togglePinnedState() {
|
||||
this.isPinned = !this.isPinned;
|
||||
if (!this.isPinned) {
|
||||
this.isExpanded = false;
|
||||
}
|
||||
Cookies.set(pinnedStateCookie, this.isPinned ? 'true' : 'false', { expires: 3650 });
|
||||
this.renderState();
|
||||
}
|
||||
|
||||
renderState() {
|
||||
$(pageSelector)
|
||||
.toggleClass(pinnedPageClass, this.isPinned && this.isExpanded)
|
||||
.toggleClass(expandedPageClass, this.isExpanded);
|
||||
$(navbarSelector)
|
||||
.toggleClass(pinnedNavbarClass, this.isPinned && this.isExpanded)
|
||||
.toggleClass(expandedNavbarClass, this.isExpanded);
|
||||
|
||||
const $pinnedToggle = $(pinnedToggleSelector);
|
||||
const tooltipText = this.isPinned ? 'Unpin navigation' : 'Pin navigation';
|
||||
const tooltipState = $pinnedToggle.attr('aria-describedby') && this.isExpanded ? 'show' : 'hide';
|
||||
$pinnedToggle.attr('title', tooltipText).tooltip('fixTitle').tooltip(tooltipState);
|
||||
|
||||
if (this.isExpanded) {
|
||||
const sidebarContent = $(sidebarContentSelector);
|
||||
setTimeout(() => { sidebarContent.niceScroll().updateScrollBar(); }, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.gl = window.gl || {};
|
||||
gl.Sidebar = Sidebar;
|
||||
})();
|
|
@ -19,7 +19,6 @@
|
|||
@import "framework/flash.scss";
|
||||
@import "framework/forms.scss";
|
||||
@import "framework/gfm.scss";
|
||||
@import "framework/gitlab-theme.scss";
|
||||
@import "framework/header.scss";
|
||||
@import "framework/highlight.scss";
|
||||
@import "framework/issue_box.scss";
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
}
|
||||
|
||||
.btn,
|
||||
.side-nav-toggle {
|
||||
.global-dropdown-toggle {
|
||||
@include transition(background-color, border-color, color, box-shadow);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,6 @@ a {
|
|||
@include transition(background-color, box-shadow);
|
||||
}
|
||||
|
||||
.nav-sidebar a,
|
||||
.dropdown-menu a,
|
||||
.dropdown-menu button,
|
||||
.dropdown-menu-nav a {
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/**
|
||||
* Styles the GitLab application with a specific color theme
|
||||
*
|
||||
* $color-light -
|
||||
* $color -
|
||||
* $color-darker -
|
||||
* $color-dark -
|
||||
*/
|
||||
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
|
||||
.page-with-sidebar {
|
||||
.toggle-nav-collapse,
|
||||
.pin-nav-btn {
|
||||
color: $color-light;
|
||||
|
||||
&:hover {
|
||||
color: $white-light;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
background: $color-darker;
|
||||
}
|
||||
|
||||
.sidebar-action-buttons {
|
||||
color: $color-light;
|
||||
background-color: lighten($color-darker, 5%);
|
||||
}
|
||||
|
||||
.nav-sidebar {
|
||||
li {
|
||||
a {
|
||||
color: $color-light;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background: $color-dark;
|
||||
}
|
||||
|
||||
i {
|
||||
color: $color-light;
|
||||
}
|
||||
|
||||
path,
|
||||
polygon {
|
||||
fill: $color-light;
|
||||
}
|
||||
|
||||
.count {
|
||||
color: $color-light;
|
||||
background: $color-dark;
|
||||
}
|
||||
|
||||
svg {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&.separate-item {
|
||||
border-top: 1px solid $color;
|
||||
}
|
||||
|
||||
&.active a {
|
||||
color: $white-light;
|
||||
background: $color-dark;
|
||||
|
||||
&.no-highlight {
|
||||
border: none;
|
||||
}
|
||||
|
||||
i {
|
||||
color: $white-light;
|
||||
}
|
||||
|
||||
path,
|
||||
polygon {
|
||||
fill: $white-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.about-gitlab {
|
||||
color: $color-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$theme-charcoal-light: #b9bbbe;
|
||||
$theme-charcoal: #485157;
|
||||
$theme-charcoal-dark: #3d454d;
|
||||
$theme-charcoal-darker: #383f45;
|
||||
|
||||
$theme-blue-light: #becde9;
|
||||
$theme-blue: #2980b9;
|
||||
$theme-blue-dark: #1970a9;
|
||||
$theme-blue-darker: #096099;
|
||||
|
||||
$theme-graphite-light: #ccc;
|
||||
$theme-graphite: #777;
|
||||
$theme-graphite-dark: #666;
|
||||
$theme-graphite-darker: #555;
|
||||
|
||||
$theme-black-light: #979797;
|
||||
$theme-black: #373737;
|
||||
$theme-black-dark: #272727;
|
||||
$theme-black-darker: #222;
|
||||
|
||||
$theme-green-light: #adc;
|
||||
$theme-green: #019875;
|
||||
$theme-green-dark: #018865;
|
||||
$theme-green-darker: #017855;
|
||||
|
||||
$theme-violet-light: #98c;
|
||||
$theme-violet: #548;
|
||||
$theme-violet-dark: #436;
|
||||
$theme-violet-darker: #325;
|
||||
|
||||
body {
|
||||
&.ui_blue {
|
||||
@include gitlab-theme($theme-blue-light, $theme-blue, $theme-blue-dark, $theme-blue-darker);
|
||||
}
|
||||
|
||||
&.ui_charcoal {
|
||||
@include gitlab-theme($theme-charcoal-light, $theme-charcoal, $theme-charcoal-dark, $theme-charcoal-darker);
|
||||
}
|
||||
|
||||
&.ui_graphite {
|
||||
@include gitlab-theme($theme-graphite-light, $theme-graphite, $theme-graphite-dark, $theme-graphite-darker);
|
||||
}
|
||||
|
||||
&.ui_black {
|
||||
@include gitlab-theme($theme-black-light, $theme-black, $theme-black-dark, $theme-black-darker);
|
||||
}
|
||||
|
||||
&.ui_green {
|
||||
@include gitlab-theme($theme-green-light, $theme-green, $theme-green-dark, $theme-green-darker);
|
||||
}
|
||||
|
||||
&.ui_violet {
|
||||
@include gitlab-theme($theme-violet-light, $theme-violet, $theme-violet-dark, $theme-violet-darker);
|
||||
}
|
||||
}
|
|
@ -100,23 +100,42 @@ header {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.side-nav-toggle {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
margin: 7px 0;
|
||||
font-size: 18px;
|
||||
padding: 6px 10px;
|
||||
border: none;
|
||||
background-color: $gray-light;
|
||||
.global-dropdown {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
|
||||
.badge {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
li {
|
||||
.active a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $white-normal;
|
||||
color: $gl-header-nav-hover-color;
|
||||
.badge {
|
||||
background-color: $white-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.global-dropdown-toggle {
|
||||
margin: 7px 0;
|
||||
font-size: 18px;
|
||||
padding: 6px 10px;
|
||||
border: none;
|
||||
background-color: $gray-light;
|
||||
|
||||
&:hover {
|
||||
background-color: $white-normal;
|
||||
color: $gl-header-nav-hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.header-content {
|
||||
position: relative;
|
||||
height: $header-height;
|
||||
|
|
|
@ -1,36 +1,3 @@
|
|||
.page-with-sidebar {
|
||||
padding-bottom: 25px;
|
||||
transition: padding $sidebar-transition-duration;
|
||||
|
||||
&.page-sidebar-pinned {
|
||||
.sidebar-wrapper {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
transition: width $sidebar-transition-duration;
|
||||
box-shadow: 2px 0 16px 0 $black-transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
z-index: 1000;
|
||||
background: $gray-light;
|
||||
|
||||
.nicescroll-rails-hr {
|
||||
// TODO: Figure out why nicescroll doesn't hide horizontal bar
|
||||
display: none!important;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
width: 100%;
|
||||
transition: padding $sidebar-transition-duration;
|
||||
|
@ -47,105 +14,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.nav-sidebar {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
bottom: 0;
|
||||
width: $sidebar_width;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.navbar-collapse {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
li {
|
||||
&.separate-item {
|
||||
padding-top: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
width: 34px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 7px $gl-sidebar-padding;
|
||||
font-size: $gl-font-size;
|
||||
line-height: 24px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
i,
|
||||
svg {
|
||||
margin-right: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.count {
|
||||
float: right;
|
||||
padding: 0 8px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.about-gitlab {
|
||||
padding: 7px $gl-sidebar-padding;
|
||||
font-size: $gl-font-size;
|
||||
line-height: 24px;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-action-buttons {
|
||||
width: $sidebar_width;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
min-height: 50px;
|
||||
padding: 5px 0;
|
||||
font-size: 18px;
|
||||
line-height: 30px;
|
||||
|
||||
.toggle-nav-collapse {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.pin-nav-btn {
|
||||
right: 0;
|
||||
display: none;
|
||||
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fa {
|
||||
transition: transform .15s;
|
||||
|
||||
.page-sidebar-pinned & {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-header-btn {
|
||||
padding: 10px $gl-sidebar-padding;
|
||||
color: inherit;
|
||||
|
@ -161,59 +29,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.page-sidebar-expanded {
|
||||
.sidebar-wrapper {
|
||||
width: $sidebar_width;
|
||||
}
|
||||
}
|
||||
|
||||
.page-sidebar-pinned {
|
||||
.content-wrapper,
|
||||
.layout-nav {
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
padding-left: $sidebar_width;
|
||||
}
|
||||
}
|
||||
|
||||
.merge-request-tabs-holder.affix {
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
left: $sidebar_width;
|
||||
}
|
||||
}
|
||||
|
||||
&.right-sidebar-expanded {
|
||||
.line-resolve-all-container {
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
header.header-sidebar-pinned {
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
padding-left: ($sidebar_width + $gl-padding);
|
||||
|
||||
.side-nav-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-sidebar-collapsed {
|
||||
padding-right: 0;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.content-wrapper {
|
||||
padding-right: $sidebar_collapsed_width;
|
||||
padding-right: $gutter_collapsed_width;
|
||||
}
|
||||
|
||||
.merge-request-tabs-holder.affix {
|
||||
right: $sidebar_collapsed_width;
|
||||
right: $gutter_collapsed_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +56,7 @@ header.header-sidebar-pinned {
|
|||
|
||||
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
|
||||
&:not(.build-sidebar):not(.wiki-sidebar) {
|
||||
padding-right: $sidebar_collapsed_width;
|
||||
padding-right: $gutter_collapsed_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,12 +70,12 @@ header.header-sidebar-pinned {
|
|||
}
|
||||
|
||||
&.with-overlay .merge-request-tabs-holder.affix {
|
||||
right: $sidebar_collapsed_width;
|
||||
right: $gutter_collapsed_width;
|
||||
}
|
||||
}
|
||||
|
||||
&.with-overlay {
|
||||
padding-right: $sidebar_collapsed_width;
|
||||
padding-right: $gutter_collapsed_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/*
|
||||
* Layout
|
||||
*/
|
||||
$sidebar_collapsed_width: 62px;
|
||||
$sidebar_width: 220px;
|
||||
$gutter_collapsed_width: 62px;
|
||||
$gutter_width: 290px;
|
||||
$gutter_inner_width: 250px;
|
||||
|
@ -541,4 +539,4 @@ Pipeline Graph
|
|||
*/
|
||||
$stage-hover-bg: #eaf3fc;
|
||||
$stage-hover-border: #d1e7fc;
|
||||
$action-icon-color: #d6d6d6;
|
||||
$action-icon-color: #d6d6d6;
|
||||
|
|
|
@ -253,11 +253,11 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
width: $sidebar_collapsed_width;
|
||||
width: $gutter_collapsed_width;
|
||||
padding-top: 0;
|
||||
|
||||
.block {
|
||||
width: $sidebar_collapsed_width - 2px;
|
||||
width: $gutter_collapsed_width - 2px;
|
||||
margin-left: -19px;
|
||||
padding: 15px 0 0;
|
||||
border-bottom: none;
|
||||
|
|
|
@ -1,42 +1,3 @@
|
|||
.application-theme {
|
||||
label {
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
|
||||
.preview {
|
||||
border-radius: 4px;
|
||||
|
||||
height: 80px;
|
||||
margin-bottom: 10px;
|
||||
width: 160px;
|
||||
|
||||
&.ui_blue {
|
||||
background: $theme-blue;
|
||||
}
|
||||
|
||||
&.ui_charcoal {
|
||||
background: $theme-charcoal;
|
||||
}
|
||||
|
||||
&.ui_graphite {
|
||||
background: $theme-graphite;
|
||||
}
|
||||
|
||||
&.ui_black {
|
||||
background: $theme-black;
|
||||
}
|
||||
|
||||
&.ui_green {
|
||||
background: $theme-green;
|
||||
}
|
||||
|
||||
&.ui_violet {
|
||||
background: $theme-violet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.syntax-theme {
|
||||
label {
|
||||
margin-right: 20px;
|
||||
|
|
|
@ -31,7 +31,6 @@ nav.navbar-collapse.collapse,
|
|||
.blob-commit-info,
|
||||
.file-title,
|
||||
.file-holder,
|
||||
.sidebar-wrapper,
|
||||
.nav,
|
||||
.btn,
|
||||
ul.notes-form,
|
||||
|
|
|
@ -194,7 +194,6 @@ class Admin::UsersController < Admin::ApplicationController
|
|||
:provider,
|
||||
:remember_me,
|
||||
:skype,
|
||||
:theme_id,
|
||||
:twitter,
|
||||
:username,
|
||||
:website_url
|
||||
|
|
|
@ -34,7 +34,6 @@ class Profiles::PreferencesController < Profiles::ApplicationController
|
|||
:layout,
|
||||
:dashboard,
|
||||
:project_view,
|
||||
:theme_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
module NavHelper
|
||||
def page_sidebar_class
|
||||
if pinned_nav?
|
||||
"page-sidebar-expanded page-sidebar-pinned"
|
||||
end
|
||||
end
|
||||
|
||||
def page_gutter_class
|
||||
if current_path?('merge_requests#show') ||
|
||||
current_path?('merge_requests#diffs') ||
|
||||
|
@ -32,10 +26,6 @@ module NavHelper
|
|||
class_name = ''
|
||||
class_name << " with-horizontal-nav" if defined?(nav) && nav
|
||||
|
||||
if pinned_nav?
|
||||
class_name << " header-sidebar-expanded header-sidebar-pinned"
|
||||
end
|
||||
|
||||
class_name
|
||||
end
|
||||
|
||||
|
@ -46,8 +36,4 @@ module NavHelper
|
|||
def nav_control_class
|
||||
"nav-control" if current_user
|
||||
end
|
||||
|
||||
def pinned_nav?
|
||||
cookies[:pin_nav] == 'true'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,10 +41,6 @@ module PreferencesHelper
|
|||
]
|
||||
end
|
||||
|
||||
def user_application_theme
|
||||
Gitlab::Themes.for_user(current_user).css_class
|
||||
end
|
||||
|
||||
def user_color_scheme
|
||||
Gitlab::ColorSchemes.for_user(current_user).css_class
|
||||
end
|
||||
|
|
|
@ -21,7 +21,6 @@ class User < ActiveRecord::Base
|
|||
default_value_for :can_create_team, false
|
||||
default_value_for :hide_no_ssh_key, false
|
||||
default_value_for :hide_no_password, false
|
||||
default_value_for :theme_id, gitlab_config.default_theme
|
||||
|
||||
attr_encrypted :otp_secret,
|
||||
key: Gitlab::Application.secrets.otp_key_base,
|
||||
|
|
|
@ -1,21 +1,4 @@
|
|||
.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" }
|
||||
.sidebar-wrapper.nicescroll
|
||||
.sidebar-action-buttons
|
||||
.nav-header-btn.toggle-nav-collapse{ title: "Open/Close" }
|
||||
%span.sr-only Toggle navigation
|
||||
= icon('bars')
|
||||
|
||||
%div{ class: "nav-header-btn pin-nav-btn has-tooltip #{'is-active' if pinned_nav?} js-nav-pin", title: pinned_nav? ? "Unpin navigation" : "Pin Navigation", data: { placement: 'right', container: 'body' } }
|
||||
%span.sr-only Toggle navigation pinning
|
||||
= icon('fw thumb-tack')
|
||||
|
||||
- if defined?(sidebar) && sidebar
|
||||
= render "layouts/nav/#{sidebar}"
|
||||
- elsif current_user
|
||||
= render 'layouts/nav/dashboard'
|
||||
- else
|
||||
= render 'layouts/nav/explore'
|
||||
|
||||
.page-with-sidebar{ class: page_gutter_class }
|
||||
- if defined?(nav) && nav
|
||||
.layout-nav
|
||||
.container-fluid
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
!!! 5
|
||||
%html{ lang: "en", class: "#{page_class}" }
|
||||
= render "layouts/head"
|
||||
%body{ class: "#{user_application_theme}", data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
|
||||
%body{ data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}" } }
|
||||
= Gon::Base.render_data
|
||||
|
||||
= render "layouts/header/default", title: header_title
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
|
||||
.container-fluid
|
||||
.header-content
|
||||
%button.side-nav-toggle{ type: 'button', "aria-label" => "Toggle global navigation" }
|
||||
%span.sr-only Toggle navigation
|
||||
= icon('bars')
|
||||
.dropdown.global-dropdown
|
||||
%button.global-dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
|
||||
%span.sr-only Toggle navigation
|
||||
= icon('bars')
|
||||
.dropdown-menu-nav.global-dropdown-menu
|
||||
- if current_user
|
||||
= render 'layouts/nav/dashboard'
|
||||
- else
|
||||
= render 'layouts/nav/explore'
|
||||
%button.navbar-toggle{ type: 'button' }
|
||||
%span.sr-only Toggle navigation
|
||||
= icon('ellipsis-v')
|
||||
|
@ -55,7 +61,6 @@
|
|||
%div
|
||||
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
|
||||
|
||||
|
||||
%h1.title= title
|
||||
|
||||
.header-logo
|
||||
|
|
|
@ -1,41 +1,39 @@
|
|||
.nav-sidebar
|
||||
%ul.nav
|
||||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
|
||||
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
|
||||
%span
|
||||
Projects
|
||||
= nav_link(path: 'dashboard#activity') do
|
||||
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
|
||||
%span
|
||||
Activity
|
||||
- if koding_enabled?
|
||||
= nav_link(controller: :koding) do
|
||||
= link_to koding_path, title: 'Koding' do
|
||||
%span
|
||||
Koding
|
||||
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
|
||||
= link_to dashboard_groups_path, title: 'Groups' do
|
||||
%span
|
||||
Groups
|
||||
= nav_link(controller: 'dashboard/milestones') do
|
||||
= link_to dashboard_milestones_path, title: 'Milestones' do
|
||||
%span
|
||||
Milestones
|
||||
= nav_link(path: 'dashboard#issues') do
|
||||
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
|
||||
%span
|
||||
Issues
|
||||
%span.count= number_with_delimiter(cached_assigned_issuables_count(current_user, :issues, :opened))
|
||||
= nav_link(path: 'dashboard#merge_requests') do
|
||||
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
|
||||
%span
|
||||
Merge Requests
|
||||
%span.count= number_with_delimiter(cached_assigned_issuables_count(current_user, :merge_requests, :opened))
|
||||
= nav_link(controller: 'dashboard/snippets') do
|
||||
= link_to dashboard_snippets_path, title: 'Snippets' do
|
||||
%span
|
||||
Snippets
|
||||
|
||||
= link_to help_path, title: 'About GitLab CE', class: 'about-gitlab' do
|
||||
%ul
|
||||
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
|
||||
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
|
||||
%span
|
||||
About GitLab CE
|
||||
Projects
|
||||
= nav_link(path: 'dashboard#activity') do
|
||||
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
|
||||
%span
|
||||
Activity
|
||||
- if koding_enabled?
|
||||
= nav_link(controller: :koding) do
|
||||
= link_to koding_path, title: 'Koding' do
|
||||
%span
|
||||
Koding
|
||||
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
|
||||
= link_to dashboard_groups_path, title: 'Groups' do
|
||||
%span
|
||||
Groups
|
||||
= nav_link(controller: 'dashboard/milestones') do
|
||||
= link_to dashboard_milestones_path, title: 'Milestones' do
|
||||
%span
|
||||
Milestones
|
||||
= nav_link(path: 'dashboard#issues') do
|
||||
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
|
||||
%span
|
||||
Issues
|
||||
%span.badge= number_with_delimiter(cached_assigned_issuables_count(current_user, :issues, :opened))
|
||||
= nav_link(path: 'dashboard#merge_requests') do
|
||||
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
|
||||
%span
|
||||
Merge Requests
|
||||
%span.badge= number_with_delimiter(cached_assigned_issuables_count(current_user, :merge_requests, :opened))
|
||||
= nav_link(controller: 'dashboard/snippets') do
|
||||
= link_to dashboard_snippets_path, title: 'Snippets' do
|
||||
%span
|
||||
Snippets
|
||||
%li.divider
|
||||
%li
|
||||
= link_to "About GitLab CE", help_path, title: 'About GitLab CE', class: 'about-gitlab'
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
%ul.nav.nav-sidebar
|
||||
%ul
|
||||
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do
|
||||
= link_to explore_root_path, title: 'Projects' do
|
||||
%span
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
Application theme
|
||||
%p
|
||||
This setting allows you to customize the appearance of the site, e.g. the sidebar.
|
||||
.col-lg-9.application-theme
|
||||
- Gitlab::Themes.each do |theme|
|
||||
= label_tag do
|
||||
.preview{ class: theme.css_class }
|
||||
= f.radio_button :theme_id, theme.id
|
||||
= theme.name
|
||||
.col-sm-12
|
||||
%hr
|
||||
.col-lg-3.profile-settings-sidebar
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
// Remove body class for any previous theme, re-add current one
|
||||
$('body').removeClass('<%= Gitlab::Themes.body_classes %>')
|
||||
$('body').addClass('<%= user_application_theme %>')
|
||||
|
||||
// Toggle container-fluid class
|
||||
if ('<%= current_user.layout %>' === 'fluid') {
|
||||
$('.content-wrapper .container-fluid').removeClass('container-limited')
|
||||
|
|
|
@ -76,14 +76,6 @@ production: &base
|
|||
|
||||
# default_can_create_group: false # default: true
|
||||
# username_changing_enabled: false # default: true - User can change her username/namespace
|
||||
## Default theme ID
|
||||
## 1 - Graphite
|
||||
## 2 - Charcoal
|
||||
## 3 - Green
|
||||
## 4 - Gray
|
||||
## 5 - Violet
|
||||
## 6 - Blue
|
||||
# default_theme: 2 # default: 2
|
||||
|
||||
## Automatic issue closing
|
||||
# If a commit message matches this regular expression, all issues referenced from the matched text will be closed.
|
||||
|
@ -611,4 +603,4 @@ test:
|
|||
admin_group: ''
|
||||
|
||||
staging:
|
||||
<<: *base
|
||||
<<: *base
|
||||
|
|
|
@ -183,7 +183,6 @@ Settings['gitlab'] ||= Settingslogic.new({})
|
|||
Settings.gitlab['default_projects_limit'] ||= 10
|
||||
Settings.gitlab['default_branch_protection'] ||= 2
|
||||
Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_can_create_group'].nil?
|
||||
Settings.gitlab['default_theme'] = Gitlab::Themes::APPLICATION_DEFAULT if Settings.gitlab['default_theme'].nil?
|
||||
Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost'
|
||||
Settings.gitlab['ssh_host'] ||= Settings.gitlab.host
|
||||
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class RemoveThemeIdFromUsers < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def change
|
||||
remove_column :users, :theme_id, :integer
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170214111112) do
|
||||
ActiveRecord::Schema.define(version: 20170215200045) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -1238,7 +1238,6 @@ ActiveRecord::Schema.define(version: 20170214111112) do
|
|||
t.string "linkedin", default: "", null: false
|
||||
t.string "twitter", default: "", null: false
|
||||
t.string "authentication_token"
|
||||
t.integer "theme_id", default: 1, null: false
|
||||
t.string "bio"
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.datetime "locked_at"
|
||||
|
@ -1351,4 +1350,4 @@ ActiveRecord::Schema.define(version: 20170214111112) do
|
|||
add_foreign_key "timelogs", "merge_requests", name: "fk_timelogs_merge_requests_merge_request_id", on_delete: :cascade
|
||||
add_foreign_key "trending_projects", "projects", on_delete: :cascade
|
||||
add_foreign_key "u2f_registrations", "users"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,6 @@ Parameters:
|
|||
"twitter": "",
|
||||
"website_url": "",
|
||||
"email": "john@example.com",
|
||||
"theme_id": 2,
|
||||
"color_scheme_id": 1,
|
||||
"projects_limit": 10,
|
||||
"current_sign_in_at": null,
|
||||
|
|
|
@ -41,7 +41,6 @@ Example response:
|
|||
"twitter": "",
|
||||
"website_url": "",
|
||||
"email": "john@example.com",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 1,
|
||||
"projects_limit": 10,
|
||||
"current_sign_in_at": "2015-07-07T07:10:58.392Z",
|
||||
|
|
|
@ -72,7 +72,6 @@ GET /users
|
|||
"organization": "",
|
||||
"last_sign_in_at": "2012-06-01T11:41:01Z",
|
||||
"confirmed_at": "2012-05-23T09:05:22Z",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 2,
|
||||
"projects_limit": 100,
|
||||
"current_sign_in_at": "2012-06-02T06:36:55Z",
|
||||
|
@ -105,7 +104,6 @@ GET /users
|
|||
"organization": "",
|
||||
"last_sign_in_at": null,
|
||||
"confirmed_at": "2012-05-30T16:53:06.148Z",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 3,
|
||||
"projects_limit": 100,
|
||||
"current_sign_in_at": "2014-03-19T17:54:13Z",
|
||||
|
@ -198,7 +196,6 @@ Parameters:
|
|||
"organization": "",
|
||||
"last_sign_in_at": "2012-06-01T11:41:01Z",
|
||||
"confirmed_at": "2012-05-23T09:05:22Z",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 2,
|
||||
"projects_limit": 100,
|
||||
"current_sign_in_at": "2012-06-02T06:36:55Z",
|
||||
|
@ -323,7 +320,6 @@ GET /user
|
|||
"organization": "",
|
||||
"last_sign_in_at": "2012-06-01T11:41:01Z",
|
||||
"confirmed_at": "2012-05-23T09:05:22Z",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 2,
|
||||
"projects_limit": 100,
|
||||
"current_sign_in_at": "2012-06-02T06:36:55Z",
|
||||
|
@ -369,7 +365,6 @@ GET /user
|
|||
"organization": "",
|
||||
"last_sign_in_at": "2012-06-01T11:41:01Z",
|
||||
"confirmed_at": "2012-05-23T09:05:22Z",
|
||||
"theme_id": 1,
|
||||
"color_scheme_id": 2,
|
||||
"projects_limit": 100,
|
||||
"current_sign_in_at": "2012-06-02T06:36:55Z",
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
@labels
|
||||
Feature: Labels
|
||||
Background:
|
||||
Given I sign in as a user
|
||||
And I own project "Shop"
|
||||
And project "Shop" has labels: "bug", "feature", "enhancement"
|
||||
When I visit project "Shop" labels page
|
||||
|
||||
@javascript
|
||||
Scenario: I can subscribe to a label
|
||||
Then I should see that I am not subscribed to the "bug" label
|
||||
When I click button "Subscribe" for the "bug" label
|
||||
Then I should see that I am subscribed to the "bug" label
|
||||
When I click button "Unsubscribe" for the "bug" label
|
||||
Then I should see that I am not subscribed to the "bug" label
|
|
@ -1,32 +0,0 @@
|
|||
class Spinach::Features::Labels < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedIssuable
|
||||
include SharedProject
|
||||
include SharedPaths
|
||||
|
||||
step 'And I visit project "Shop" labels page' do
|
||||
visit namespace_project_labels_path(project.namespace, project)
|
||||
end
|
||||
|
||||
step 'I should see that I am subscribed to the "bug" label' do
|
||||
expect(subscribe_button).to have_content 'Unsubscribe'
|
||||
end
|
||||
|
||||
step 'I should see that I am not subscribed to the "bug" label' do
|
||||
expect(subscribe_button).to have_content 'Subscribe'
|
||||
end
|
||||
|
||||
step 'I click button "Unsubscribe" for the "bug" label' do
|
||||
subscribe_button.click
|
||||
end
|
||||
|
||||
step 'I click button "Subscribe" for the "bug" label' do
|
||||
subscribe_button.click
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def subscribe_button
|
||||
first('.js-subscribe-button', visible: true)
|
||||
end
|
||||
end
|
|
@ -26,7 +26,7 @@ module API
|
|||
expose :last_sign_in_at
|
||||
expose :confirmed_at
|
||||
expose :email
|
||||
expose :theme_id, :color_scheme_id, :projects_limit, :current_sign_in_at
|
||||
expose :color_scheme_id, :projects_limit, :current_sign_in_at
|
||||
expose :identities, using: Entities::Identity
|
||||
expose :can_create_group?, as: :can_create_group
|
||||
expose :can_create_project?, as: :can_create_project
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
module Gitlab
|
||||
# Module containing GitLab's application theme definitions and helper methods
|
||||
# for accessing them.
|
||||
module Themes
|
||||
extend self
|
||||
|
||||
# Theme ID used when no `default_theme` configuration setting is provided.
|
||||
APPLICATION_DEFAULT = 2
|
||||
|
||||
# Struct class representing a single Theme
|
||||
Theme = Struct.new(:id, :name, :css_class)
|
||||
|
||||
# All available Themes
|
||||
THEMES = [
|
||||
Theme.new(1, 'Graphite', 'ui_graphite'),
|
||||
Theme.new(2, 'Charcoal', 'ui_charcoal'),
|
||||
Theme.new(3, 'Green', 'ui_green'),
|
||||
Theme.new(4, 'Black', 'ui_black'),
|
||||
Theme.new(5, 'Violet', 'ui_violet'),
|
||||
Theme.new(6, 'Blue', 'ui_blue')
|
||||
].freeze
|
||||
|
||||
# Convenience method to get a space-separated String of all the theme
|
||||
# classes that might be applied to the `body` element
|
||||
#
|
||||
# Returns a String
|
||||
def body_classes
|
||||
THEMES.collect(&:css_class).uniq.join(' ')
|
||||
end
|
||||
|
||||
# Get a Theme by its ID
|
||||
#
|
||||
# If the ID is invalid, returns the default Theme.
|
||||
#
|
||||
# id - Integer ID
|
||||
#
|
||||
# Returns a Theme
|
||||
def by_id(id)
|
||||
THEMES.detect { |t| t.id == id } || default
|
||||
end
|
||||
|
||||
# Returns the number of defined Themes
|
||||
def count
|
||||
THEMES.size
|
||||
end
|
||||
|
||||
# Get the default Theme
|
||||
#
|
||||
# Returns a Theme
|
||||
def default
|
||||
by_id(default_id)
|
||||
end
|
||||
|
||||
# Iterate through each Theme
|
||||
#
|
||||
# Yields the Theme object
|
||||
def each(&block)
|
||||
THEMES.each(&block)
|
||||
end
|
||||
|
||||
# Get the Theme for the specified user, or the default
|
||||
#
|
||||
# user - User record
|
||||
#
|
||||
# Returns a Theme
|
||||
def for_user(user)
|
||||
if user
|
||||
by_id(user.theme_id)
|
||||
else
|
||||
default
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_id
|
||||
id = Gitlab.config.gitlab.default_theme.to_i
|
||||
|
||||
# Prevent an invalid configuration setting from causing an infinite loop
|
||||
if id < THEMES.first.id || id > THEMES.last.id
|
||||
APPLICATION_DEFAULT
|
||||
else
|
||||
id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -25,8 +25,7 @@ describe Profiles::PreferencesController do
|
|||
def go(params: {}, format: :js)
|
||||
params.reverse_merge!(
|
||||
color_scheme_id: '1',
|
||||
dashboard: 'stars',
|
||||
theme_id: '1'
|
||||
dashboard: 'stars'
|
||||
)
|
||||
|
||||
patch :update, user: params, format: format
|
||||
|
@ -41,8 +40,7 @@ describe Profiles::PreferencesController do
|
|||
it "changes the user's preferences" do
|
||||
prefs = {
|
||||
color_scheme_id: '1',
|
||||
dashboard: 'stars',
|
||||
theme_id: '2'
|
||||
dashboard: 'stars'
|
||||
}.with_indifferent_access
|
||||
|
||||
expect(user).to receive(:update_attributes).with(prefs)
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Dashboard Active Tab', feature: true do
|
||||
RSpec.describe 'Dashboard Active Tab', js: true, feature: true do
|
||||
before do
|
||||
login_as :user
|
||||
end
|
||||
|
||||
shared_examples 'page has active tab' do |title|
|
||||
it "#{title} tab" do
|
||||
expect(page).to have_selector('.nav-sidebar li.active', count: 1)
|
||||
expect(find('.nav-sidebar li.active')).to have_content(title)
|
||||
find('.global-dropdown-toggle').trigger('click')
|
||||
expect(page).to have_selector('.global-dropdown-menu li.active', count: 1)
|
||||
expect(find('.global-dropdown-menu li.active')).to have_content(title)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ describe 'Navigation bar counter', feature: true, js: true, caching: true do
|
|||
|
||||
def expect_counters(issuable_type, count)
|
||||
dashboard_count = find('li.active span.badge')
|
||||
nav_count = find(".dashboard-shortcuts-#{issuable_type} span.count")
|
||||
find('.global-dropdown-toggle').click
|
||||
nav_count = find(".dashboard-shortcuts-#{issuable_type} span.badge")
|
||||
|
||||
expect(nav_count).to have_content(count)
|
||||
expect(dashboard_count).to have_content(count)
|
||||
|
|
|
@ -10,20 +10,20 @@ feature 'Dashboard shortcuts', feature: true, js: true do
|
|||
find('body').native.send_key('g')
|
||||
find('body').native.send_key('p')
|
||||
|
||||
ensure_active_main_tab('Projects')
|
||||
check_page_title('Projects')
|
||||
|
||||
find('body').native.send_key('g')
|
||||
find('body').native.send_key('i')
|
||||
|
||||
ensure_active_main_tab('Issues')
|
||||
check_page_title('Issues')
|
||||
|
||||
find('body').native.send_key('g')
|
||||
find('body').native.send_key('m')
|
||||
|
||||
ensure_active_main_tab('Merge Requests')
|
||||
check_page_title('Merge Requests')
|
||||
end
|
||||
|
||||
def ensure_active_main_tab(content)
|
||||
expect(find('.nav-sidebar li.active')).to have_content(content)
|
||||
def check_page_title(title)
|
||||
expect(find('.header-content .title')).to have_content(title)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,35 +8,6 @@ describe 'Profile > Preferences', feature: true do
|
|||
visit profile_preferences_path
|
||||
end
|
||||
|
||||
describe 'User changes their application theme', js: true do
|
||||
let(:default) { Gitlab::Themes.default }
|
||||
let(:theme) { Gitlab::Themes.by_id(5) }
|
||||
|
||||
it 'creates a flash message' do
|
||||
choose "user_theme_id_#{theme.id}"
|
||||
|
||||
expect_preferences_saved_message
|
||||
end
|
||||
|
||||
it 'updates their preference' do
|
||||
choose "user_theme_id_#{theme.id}"
|
||||
|
||||
allowing_for_delay do
|
||||
visit page.current_path
|
||||
expect(page).to have_checked_field("user_theme_id_#{theme.id}")
|
||||
end
|
||||
end
|
||||
|
||||
it 'reflects the changes immediately' do
|
||||
expect(page).to have_selector("body.#{default.css_class}")
|
||||
|
||||
choose "user_theme_id_#{theme.id}"
|
||||
|
||||
expect(page).not_to have_selector("body.#{default.css_class}")
|
||||
expect(page).to have_selector("body.#{theme.css_class}")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'User changes their syntax highlighting theme', js: true do
|
||||
it 'creates a flash message' do
|
||||
choose 'user_color_scheme_id_5'
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
"organization",
|
||||
"last_sign_in_at",
|
||||
"confirmed_at",
|
||||
"theme_id",
|
||||
"color_scheme_id",
|
||||
"projects_limit",
|
||||
"current_sign_in_at",
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
"organization",
|
||||
"last_sign_in_at",
|
||||
"confirmed_at",
|
||||
"theme_id",
|
||||
"color_scheme_id",
|
||||
"projects_limit",
|
||||
"current_sign_in_at",
|
||||
|
@ -32,14 +31,14 @@
|
|||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"username": { "type": "string" },
|
||||
"email": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"pattern": "^[^@]+@[^@]+$"
|
||||
},
|
||||
"name": { "type": "string" },
|
||||
"state": {
|
||||
"state": {
|
||||
"type": "string",
|
||||
"enum": ["active", "blocked"]
|
||||
"enum": ["active", "blocked"]
|
||||
},
|
||||
"avatar_url": { "type": "string" },
|
||||
"web_url": { "type": "string" },
|
||||
|
@ -54,18 +53,17 @@
|
|||
"organization": { "type": ["string", "null"] },
|
||||
"last_sign_in_at": { "type": "date" },
|
||||
"confirmed_at": { "type": ["date", "null"] },
|
||||
"theme_id": { "type": "integer" },
|
||||
"color_scheme_id": { "type": "integer" },
|
||||
"projects_limit": { "type": "integer" },
|
||||
"current_sign_in_at": { "type": "date" },
|
||||
"identities": {
|
||||
"identities": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"provider": {
|
||||
"provider": {
|
||||
"type": "string",
|
||||
"enum": ["github", "bitbucket", "google_oauth2"]
|
||||
"enum": ["github", "bitbucket", "google_oauth2"]
|
||||
},
|
||||
"extern_uid": { "type": ["number", "string"] }
|
||||
}
|
||||
|
@ -74,6 +72,6 @@
|
|||
"can_create_group": { "type": "boolean" },
|
||||
"can_create_project": { "type": "boolean" },
|
||||
"two_factor_enabled": { "type": "boolean" },
|
||||
"external": { "type": "boolean" }
|
||||
"external": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,32 +26,6 @@ describe PreferencesHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'user_application_theme' do
|
||||
context 'with a user' do
|
||||
it "returns user's theme's css_class" do
|
||||
stub_user(theme_id: 3)
|
||||
|
||||
expect(helper.user_application_theme).to eq 'ui_green'
|
||||
end
|
||||
|
||||
it 'returns the default when id is invalid' do
|
||||
stub_user(theme_id: Gitlab::Themes.count + 5)
|
||||
|
||||
allow(Gitlab.config.gitlab).to receive(:default_theme).and_return(2)
|
||||
|
||||
expect(helper.user_application_theme).to eq 'ui_charcoal'
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a user' do
|
||||
it 'returns the default theme' do
|
||||
stub_user
|
||||
|
||||
expect(helper.user_application_theme).to eq Gitlab::Themes.default.css_class
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user_color_scheme' do
|
||||
context 'with a user' do
|
||||
it "returns user's scheme's css_class" do
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* eslint-disable no-new */
|
||||
|
||||
require('~/sidebar');
|
||||
require('~/lib/utils/text_utility');
|
||||
|
||||
((global) => {
|
||||
describe('Dashboard', () => {
|
||||
const fixtureTemplate = 'static/dashboard.html.raw';
|
||||
|
||||
function todosCountText() {
|
||||
return $('.js-todos-count').text();
|
||||
}
|
||||
|
||||
function triggerToggle(newCount) {
|
||||
$(document).trigger('todo:toggle', newCount);
|
||||
}
|
||||
|
||||
preloadFixtures(fixtureTemplate);
|
||||
beforeEach(() => {
|
||||
loadFixtures(fixtureTemplate);
|
||||
new global.Sidebar();
|
||||
});
|
||||
|
||||
it('should update todos-count after receiving the todo:toggle event', () => {
|
||||
triggerToggle(5);
|
||||
expect(todosCountText()).toEqual('5');
|
||||
});
|
||||
|
||||
it('should display todos-count with delimiter', () => {
|
||||
triggerToggle(1000);
|
||||
expect(todosCountText()).toEqual('1,000');
|
||||
|
||||
triggerToggle(1000000);
|
||||
expect(todosCountText()).toEqual('1,000,000');
|
||||
});
|
||||
});
|
||||
})(window.gl);
|
|
@ -1,45 +0,0 @@
|
|||
%ul.nav.nav-sidebar
|
||||
%li.home.active
|
||||
%a.dashboard-shortcuts-projects
|
||||
%span
|
||||
Projects
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Todos
|
||||
%span.count.js-todos-count
|
||||
1
|
||||
%li
|
||||
%a.dashboard-shortcuts-activity
|
||||
%span
|
||||
Activity
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Groups
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Milestones
|
||||
%li
|
||||
%a.dashboard-shortcuts-issues
|
||||
%span
|
||||
Issues
|
||||
%span
|
||||
1
|
||||
%li
|
||||
%a.dashboard-shortcuts-merge_requests
|
||||
%span
|
||||
Merge Requests
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Snippets
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Help
|
||||
%li
|
||||
%a
|
||||
%span
|
||||
Profile Settings
|
|
@ -1,86 +0,0 @@
|
|||
require('~/sidebar');
|
||||
|
||||
(() => {
|
||||
describe('Project dashboard page', () => {
|
||||
let $pageWithSidebar = null;
|
||||
let $sidebarToggle = null;
|
||||
let sidebar = null;
|
||||
const fixtureTemplate = 'projects/dashboard.html.raw';
|
||||
|
||||
const assertSidebarStateExpanded = (shouldBeExpanded) => {
|
||||
expect(sidebar.isExpanded).toBe(shouldBeExpanded);
|
||||
expect($pageWithSidebar.hasClass('page-sidebar-expanded')).toBe(shouldBeExpanded);
|
||||
};
|
||||
|
||||
preloadFixtures(fixtureTemplate);
|
||||
beforeEach(() => {
|
||||
loadFixtures(fixtureTemplate);
|
||||
|
||||
$pageWithSidebar = $('.page-with-sidebar');
|
||||
$sidebarToggle = $('.toggle-nav-collapse');
|
||||
|
||||
// otherwise instantiating the Sidebar for the second time
|
||||
// won't do anything, as the Sidebar is a singleton class
|
||||
gl.Sidebar.singleton = null;
|
||||
sidebar = new gl.Sidebar();
|
||||
});
|
||||
|
||||
it('can show the sidebar when the toggler is clicked', () => {
|
||||
assertSidebarStateExpanded(false);
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when clone button clicked', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
const cloneButton = $('.project-clone-holder a.clone-dropdown-btn');
|
||||
cloneButton.click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when download button clicked', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
const downloadButton = $('.project-action-button .btn:has(i.fa-download)');
|
||||
downloadButton.click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when add button clicked', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
const addButton = $('.project-action-button .btn:has(i.fa-plus)');
|
||||
addButton.click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when notification button clicked', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
const notifButton = $('.js-notification-toggle-btns .notifications-btn');
|
||||
notifButton.click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when clicking on the body', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
$('body').click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
|
||||
it('should dismiss the sidebar when clicking on the project description header', () => {
|
||||
$sidebarToggle.click();
|
||||
assertSidebarStateExpanded(true);
|
||||
|
||||
$('.project-home-panel').click();
|
||||
assertSidebarStateExpanded(false);
|
||||
});
|
||||
});
|
||||
})();
|
|
@ -1,48 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Themes, lib: true do
|
||||
describe '.body_classes' do
|
||||
it 'returns a space-separated list of class names' do
|
||||
css = described_class.body_classes
|
||||
|
||||
expect(css).to include('ui_graphite')
|
||||
expect(css).to include(' ui_charcoal ')
|
||||
expect(css).to include(' ui_blue')
|
||||
end
|
||||
end
|
||||
|
||||
describe '.by_id' do
|
||||
it 'returns a Theme by its ID' do
|
||||
expect(described_class.by_id(1).name).to eq 'Graphite'
|
||||
expect(described_class.by_id(6).name).to eq 'Blue'
|
||||
end
|
||||
end
|
||||
|
||||
describe '.default' do
|
||||
it 'returns the default application theme' do
|
||||
allow(described_class).to receive(:default_id).and_return(2)
|
||||
expect(described_class.default.id).to eq 2
|
||||
end
|
||||
|
||||
it 'prevents an infinite loop when configuration default is invalid' do
|
||||
default = described_class::APPLICATION_DEFAULT
|
||||
themes = described_class::THEMES
|
||||
|
||||
config = double(default_theme: 0).as_null_object
|
||||
allow(Gitlab).to receive(:config).and_return(config)
|
||||
expect(described_class.default.id).to eq default
|
||||
|
||||
config = double(default_theme: themes.size + 5).as_null_object
|
||||
allow(Gitlab).to receive(:config).and_return(config)
|
||||
expect(described_class.default.id).to eq default
|
||||
end
|
||||
end
|
||||
|
||||
describe '.each' do
|
||||
it 'passes the block to the THEMES Array' do
|
||||
ids = []
|
||||
described_class.each { |theme| ids << theme.id }
|
||||
expect(ids).not_to be_empty
|
||||
end
|
||||
end
|
||||
end
|
|
@ -582,18 +582,16 @@ describe User, models: true do
|
|||
it "applies defaults to user" do
|
||||
expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit)
|
||||
expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group)
|
||||
expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme)
|
||||
expect(user.external).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with default overrides' do
|
||||
let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true, theme_id: 1) }
|
||||
let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true) }
|
||||
|
||||
it "applies defaults to user" do
|
||||
expect(user.projects_limit).to eq(123)
|
||||
expect(user.can_create_group).to be_falsey
|
||||
expect(user.theme_id).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"skype":"aertert",
|
||||
"linkedin":"",
|
||||
"twitter":"",
|
||||
"theme_id":2,"color_scheme_id":2,
|
||||
"color_scheme_id":2,
|
||||
"state":"active",
|
||||
"created_at":"2012-12-21T13:02:20Z",
|
||||
"extern_uid":null,
|
||||
|
@ -17,4 +17,4 @@
|
|||
"can_create_project":false,
|
||||
"private_token":"Wvjy2Krpb7y8xi93owUz",
|
||||
"access_token":"Wvjy2Krpb7y8xi93owUz"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"skype":"aertert",
|
||||
"linkedin":"",
|
||||
"twitter":"",
|
||||
"theme_id":2,"color_scheme_id":2,
|
||||
"color_scheme_id":2,
|
||||
"state":"active",
|
||||
"created_at":"2012-12-21T13:02:20Z",
|
||||
"extern_uid":null,
|
||||
|
@ -17,4 +17,4 @@
|
|||
"can_create_project":false,
|
||||
"private_token":"Wvjy2Krpb7y8xi93owUz",
|
||||
"access_token":"Wvjy2Krpb7y8xi93owUz"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue