Commit 2aa8a75f authored by Phil Hughes's avatar Phil Hughes

Merge branch 'master' into breadcrumbs-improvements

parents de82bd8e 1632ffa6
...@@ -208,7 +208,7 @@ update-tests-metadata: ...@@ -208,7 +208,7 @@ update-tests-metadata:
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH' - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH' - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json - rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
- rm -f rspec_flaky/${CI_PROJECT_NAME}/all_node_*.json - rm -f rspec_flaky/${CI_PROJECT_NAME}/*_node_*.json
flaky-examples-check: flaky-examples-check:
<<: *dedicated-runner <<: *dedicated-runner
......
...@@ -181,7 +181,7 @@ gem 'connection_pool', '~> 2.0' ...@@ -181,7 +181,7 @@ gem 'connection_pool', '~> 2.0'
gem 'hipchat', '~> 1.5.0' gem 'hipchat', '~> 1.5.0'
# JIRA integration # JIRA integration
gem 'jira-ruby', '~> 1.1.2' gem 'jira-ruby', '~> 1.4'
# Flowdock integration # Flowdock integration
gem 'gitlab-flowdock-git-hook', '~> 1.0.1' gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
...@@ -397,7 +397,7 @@ group :ed25519 do ...@@ -397,7 +397,7 @@ group :ed25519 do
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly-proto', '~> 0.31.0', require: 'gitaly' gem 'gitaly-proto', '~> 0.32.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -275,7 +275,7 @@ GEM ...@@ -275,7 +275,7 @@ GEM
po_to_json (>= 1.0.0) po_to_json (>= 1.0.0)
rails (>= 3.2.0) rails (>= 3.2.0)
gherkin-ruby (0.3.2) gherkin-ruby (0.3.2)
gitaly-proto (0.31.0) gitaly-proto (0.32.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
grpc (~> 1.0) grpc (~> 1.0)
github-linguist (4.7.6) github-linguist (4.7.6)
...@@ -404,8 +404,9 @@ GEM ...@@ -404,8 +404,9 @@ GEM
cause cause
json json
ipaddress (0.8.3) ipaddress (0.8.3)
jira-ruby (1.1.2) jira-ruby (1.4.1)
activesupport activesupport
multipart-post
oauth (~> 0.5, >= 0.5.0) oauth (~> 0.5, >= 0.5.0)
jquery-atwho-rails (1.3.2) jquery-atwho-rails (1.3.2)
jquery-rails (4.1.1) jquery-rails (4.1.1)
...@@ -1020,7 +1021,7 @@ DEPENDENCIES ...@@ -1020,7 +1021,7 @@ DEPENDENCIES
gettext (~> 3.2.2) gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0) gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.31.0) gitaly-proto (~> 0.32.0)
github-linguist (~> 4.7.0) github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1) gitlab-markup (~> 1.5.1)
...@@ -1042,7 +1043,7 @@ DEPENDENCIES ...@@ -1042,7 +1043,7 @@ DEPENDENCIES
html2text html2text
httparty (~> 0.13.3) httparty (~> 0.13.3)
influxdb (~> 0.2) influxdb (~> 0.2)
jira-ruby (~> 1.1.2) jira-ruby (~> 1.4)
jquery-atwho-rails (~> 1.3.2) jquery-atwho-rails (~> 1.3.2)
jquery-rails (~> 4.1.0) jquery-rails (~> 4.1.0)
json-schema (~> 2.6.2) json-schema (~> 2.6.2)
......
...@@ -61,7 +61,7 @@ class DropdownHint extends gl.FilteredSearchDropdown { ...@@ -61,7 +61,7 @@ class DropdownHint extends gl.FilteredSearchDropdown {
.map(tokenKey => ({ .map(tokenKey => ({
icon: `fa-${tokenKey.icon}`, icon: `fa-${tokenKey.icon}`,
hint: tokenKey.key, hint: tokenKey.key,
tag: `<${tokenKey.tag}>`, tag: `:${tokenKey.tag}`,
type: tokenKey.type, type: tokenKey.type,
})); }));
......
...@@ -637,11 +637,15 @@ GitLabDropdown = (function() { ...@@ -637,11 +637,15 @@ GitLabDropdown = (function() {
value = this.options.id ? this.options.id(data) : data.id; value = this.options.id ? this.options.id(data) : data.id;
fieldName = this.options.fieldName; fieldName = this.options.fieldName;
if (value) { value = value.toString().replace(/'/g, '\\\''); } if (value) {
value = value.toString().replace(/'/g, '\\\'');
field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']"); field = this.dropdown.parent().find(`input[name='${fieldName}'][value='${value}']`);
if (field.length) { if (field.length) {
selected = true; selected = true;
}
} else {
field = this.dropdown.parent().find(`input[name='${fieldName}']`);
selected = !field.length;
} }
} }
// Set URL // Set URL
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
/* global SubscriptionSelect */ /* global SubscriptionSelect */
import IssuableBulkUpdateActions from './issuable_bulk_update_actions'; import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import SidebarHeightManager from './sidebar_height_manager';
const HIDDEN_CLASS = 'hidden'; const HIDDEN_CLASS = 'hidden';
const DISABLED_CONTENT_CLASS = 'disabled-content'; const DISABLED_CONTENT_CLASS = 'disabled-content';
...@@ -50,13 +49,6 @@ export default class IssuableBulkUpdateSidebar { ...@@ -50,13 +49,6 @@ export default class IssuableBulkUpdateSidebar {
new SubscriptionSelect(); new SubscriptionSelect();
} }
getNavHeight() {
const navbarHeight = $('.navbar-gitlab').outerHeight();
const layoutNavHeight = $('.layout-nav').outerHeight();
const subNavScroll = $('.sub-nav-scroll').outerHeight();
return navbarHeight + layoutNavHeight + subNavScroll;
}
setupBulkUpdateActions() { setupBulkUpdateActions() {
IssuableBulkUpdateActions.setOriginalDropdownData(); IssuableBulkUpdateActions.setOriginalDropdownData();
} }
...@@ -84,23 +76,6 @@ export default class IssuableBulkUpdateSidebar { ...@@ -84,23 +76,6 @@ export default class IssuableBulkUpdateSidebar {
this.toggleBulkEditButtonDisabled(enable); this.toggleBulkEditButtonDisabled(enable);
this.toggleOtherFiltersDisabled(enable); this.toggleOtherFiltersDisabled(enable);
this.toggleCheckboxDisplay(enable); this.toggleCheckboxDisplay(enable);
if (enable) {
this.initAffix();
SidebarHeightManager.init();
}
}
initAffix() {
if (!this.$sidebar.hasClass('affix-top')) {
const offsetTop = $('.scrolling-tabs-container').outerHeight() + $('.sub-nav-scroll').outerHeight();
this.$sidebar.affix({
offset: {
top: offsetTop,
},
});
}
} }
updateSelectedIssuableIds() { updateSelectedIssuableIds() {
......
...@@ -50,19 +50,10 @@ import initFlyOutNav from './fly_out_nav'; ...@@ -50,19 +50,10 @@ import initFlyOutNav from './fly_out_nav';
}); });
}); });
function applyScrollNavClass() {
const scrollOpacityHeight = 40;
$('.navbar-border').css('opacity', Math.min($(window).scrollTop() / scrollOpacityHeight, 1));
}
$(() => { $(() => {
if (Cookies.get('new_nav') === 'true') { const newNavSidebar = new NewNavSidebar();
const newNavSidebar = new NewNavSidebar(); newNavSidebar.bindEvents();
newNavSidebar.bindEvents();
initFlyOutNav();
}
$(window).on('scroll', _.throttle(applyScrollNavClass, 100)); initFlyOutNav();
}); });
}).call(window); }).call(window);
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import statusCodes from '../../lib/utils/http_status'; import statusCodes from '../../lib/utils/http_status';
import MonitoringService from '../services/monitoring_service'; import MonitoringService from '../services/monitoring_service';
import GraphGroup from './graph_group.vue'; import GraphGroup from './graph_group.vue';
import GraphRow from './graph_row.vue'; import Graph from './graph.vue';
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store'; import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
}, },
components: { components: {
Graph,
GraphGroup, GraphGroup,
GraphRow,
EmptyState, EmptyState,
}, },
...@@ -127,10 +127,10 @@ ...@@ -127,10 +127,10 @@
:key="index" :key="index"
:name="groupData.group" :name="groupData.group"
> >
<graph-row <graph
v-for="(row, index) in groupData.metrics" v-for="(graphData, index) in groupData.metrics"
:key="index" :key="index"
:row-data="row" :graph-data="graphData"
:update-aspect-ratio="updateAspectRatio" :update-aspect-ratio="updateAspectRatio"
:deployment-data="store.deploymentData" :deployment-data="store.deploymentData"
/> />
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
type: Object, type: Object,
required: true, required: true,
}, },
classType: {
type: String,
required: true,
},
updateAspectRatio: { updateAspectRatio: {
type: Boolean, type: Boolean,
required: true, required: true,
...@@ -207,12 +203,11 @@ ...@@ -207,12 +203,11 @@
}, },
}; };
</script> </script>
<template> <template>
<div <div class="prometheus-graph">
:class="classType"> <h5 class="text-center graph-title">
<h5 {{graphData.title}}
class="text-center graph-title">
{{graphData.title}}
</h5> </h5>
<div <div
class="prometheus-svg-container" class="prometheus-svg-container"
...@@ -243,7 +238,7 @@ ...@@ -243,7 +238,7 @@
class="graph-data" class="graph-data"
:viewBox="innerViewBox" :viewBox="innerViewBox"
ref="graphData"> ref="graphData">
<monitoring-paths <monitoring-paths
v-for="(path, index) in timeSeries" v-for="(path, index) in timeSeries"
:key="index" :key="index"
:generated-line-path="path.linePath" :generated-line-path="path.linePath"
......
...@@ -14,7 +14,7 @@ export default { ...@@ -14,7 +14,7 @@ export default {
<div class="panel-heading"> <div class="panel-heading">
<h4>{{name}}</h4> <h4>{{name}}</h4>
</div> </div>
<div class="panel-body"> <div class="panel-body prometheus-graph-group">
<slot /> <slot />
</div> </div>
</div> </div>
......
<script>
import Graph from './graph.vue';
export default {
props: {
rowData: {
type: Array,
required: true,
},
updateAspectRatio: {
type: Boolean,
required: true,
},
deploymentData: {
type: Array,
required: true,
},
},
components: {
Graph,
},
computed: {
bootstrapClass() {
return this.rowData.length >= 2 ? 'col-md-6' : 'col-md-12';
},
},
};
</script>
<template>
<div class="prometheus-row row">
<graph
v-for="(graphData, index) in rowData"
:graph-data="graphData"
:class-type="bootstrapClass"
:key="index"
:update-aspect-ratio="updateAspectRatio"
:deployment-data="deploymentData"
/>
</div>
</template>
...@@ -20,22 +20,6 @@ function normalizeMetrics(metrics) { ...@@ -20,22 +20,6 @@ function normalizeMetrics(metrics) {
})); }));
} }
function collate(array, rows = 2) {
const collatedArray = [];
let row = [];
array.forEach((value, index) => {
row.push(value);
if ((index + 1) % rows === 0) {
collatedArray.push(row);
row = [];
}
});
if (row.length > 0) {
collatedArray.push(row);
}
return collatedArray;
}
export default class MonitoringStore { export default class MonitoringStore {
constructor() { constructor() {
this.groups = []; this.groups = [];
...@@ -45,7 +29,7 @@ export default class MonitoringStore { ...@@ -45,7 +29,7 @@ export default class MonitoringStore {
storeMetrics(groups = []) { storeMetrics(groups = []) {
this.groups = groups.map(group => ({ this.groups = groups.map(group => ({
...group, ...group,
metrics: collate(normalizeMetrics(sortMetrics(group.metrics))), metrics: normalizeMetrics(sortMetrics(group.metrics)),
})); }));
} }
...@@ -54,12 +38,6 @@ export default class MonitoringStore { ...@@ -54,12 +38,6 @@ export default class MonitoringStore {
} }
getMetricsCount() { getMetricsCount() {
let metricsCount = 0; return this.groups.reduce((count, group) => count + group.metrics.length, 0);
this.groups.forEach((group) => {
group.metrics.forEach((metric) => {
metricsCount = metricsCount += metric.length;
});
});
return metricsCount;
} }
} }
...@@ -63,7 +63,7 @@ export default class NewNavSidebar { ...@@ -63,7 +63,7 @@ export default class NewNavSidebar {
if (breakpoint === 'sm' || breakpoint === 'md') { if (breakpoint === 'sm' || breakpoint === 'md') {
this.toggleCollapsedSidebar(true); this.toggleCollapsedSidebar(true);
} else if (breakpoint === 'lg') { } else if (breakpoint === 'lg') {
const collapse = Cookies.get('sidebar_collapsed') === 'true'; const collapse = this.$sidebar.hasClass('sidebar-icons-only');
this.toggleCollapsedSidebar(collapse); this.toggleCollapsedSidebar(collapse);
} }
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import _ from 'underscore'; import _ from 'underscore';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import SidebarHeightManager from './sidebar_height_manager';
(function() { (function() {
this.Sidebar = (function() { this.Sidebar = (function() {
...@@ -23,7 +22,6 @@ import SidebarHeightManager from './sidebar_height_manager'; ...@@ -23,7 +22,6 @@ import SidebarHeightManager from './sidebar_height_manager';
}; };
Sidebar.prototype.addEventListeners = function() { Sidebar.prototype.addEventListeners = function() {
SidebarHeightManager.init();
const $document = $(document); const $document = $(document);
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked); this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
......
import _ from 'underscore';
import Cookies from 'js-cookie';
export default {
init() {
if (!this.initialized) {
if (Cookies.get('new_nav') === 'true' && $('.js-issuable-sidebar').length) return;
this.$window = $(window);
this.$rightSidebar = $('.js-right-sidebar');
this.$navHeight = $('.navbar-gitlab').outerHeight() +
$('.layout-nav').outerHeight() +
$('.sub-nav-scroll').outerHeight();
const throttledSetSidebarHeight = _.throttle(() => this.setSidebarHeight(), 20);
const debouncedSetSidebarHeight = _.debounce(() => this.setSidebarHeight(), 200);
this.$window.on('scroll', throttledSetSidebarHeight);
this.$window.on('resize', debouncedSetSidebarHeight);
this.initialized = true;
}
},
setSidebarHeight() {
const currentScrollDepth = window.pageYOffset || 0;
const diff = this.$navHeight - currentScrollDepth;
if (diff > 0) {
const newSidebarHeight = window.innerHeight - diff;
this.$rightSidebar.outerHeight(newSidebarHeight);
this.sidebarHeightIsCustom = true;
} else if (this.sidebarHeightIsCustom) {
this.$rightSidebar.outerHeight('100%');
this.sidebarHeightIsCustom = false;
}
},
};
...@@ -766,6 +766,7 @@ ...@@ -766,6 +766,7 @@
box-shadow: none; box-shadow: none;
padding: 8px 16px; padding: 8px 16px;
text-align: left; text-align: left;
white-space: normal;
width: 100%; width: 100%;
// make sure the text color is not overriden // make sure the text color is not overriden
......
...@@ -105,12 +105,11 @@ header { ...@@ -105,12 +105,11 @@ header {
top: -3px; top: -3px;
font-size: 10px; font-size: 10px;
} }
}
.user-counter {
svg { svg {
position: relative; height: 16px;
top: 2px;
height: 17px;
// hack to get SVG to line up with FA icons
width: 23px; width: 23px;
fill: currentColor; fill: currentColor;
} }
...@@ -325,12 +324,12 @@ header { ...@@ -325,12 +324,12 @@ header {
li { li {
.badge { .badge {
position: inherit; position: inherit;
top: -8px;
font-weight: $gl-font-weight-normal; font-weight: $gl-font-weight-normal;
margin-left: -11px; margin-left: -6px;
font-size: 11px; font-size: 11px;
color: $white-light; color: $white-light;
padding: 1px 5px 2px; padding: 0 5px;
line-height: 12px;
border-radius: 7px; border-radius: 7px;
box-shadow: 0 1px 0 rgba($gl-header-color, .2); box-shadow: 0 1px 0 rgba($gl-header-color, .2);
......
...@@ -177,13 +177,14 @@ $row-hover: $blue-25; ...@@ -177,13 +177,14 @@ $row-hover: $blue-25;
$row-hover-border: $blue-100; $row-hover-border: $blue-100;
$progress-color: #c0392b; $progress-color: #c0392b;
$header-height: 50px; $header-height: 50px;
$new-navbar-height: 40px;
$fixed-layout-width: 1280px; $fixed-layout-width: 1280px;
$limited-layout-width: 990px; $limited-layout-width: 990px;
$limited-layout-width-sm: 790px; $limited-layout-width-sm: 790px;
$container-text-max-width: 540px; $container-text-max-width: 540px;
$gl-avatar-size: 40px; $gl-avatar-size: 40px;
$error-exclamation-point: $red-500; $error-exclamation-point: $red-500;
$border-radius-default: 3px; $border-radius-default: 4px;
$settings-icon-size: 18px; $settings-icon-size: 18px;
$provider-btn-not-active-color: $blue-500; $provider-btn-not-active-color: $blue-500;
$link-underline-blue: $blue-500; $link-underline-blue: $blue-500;
......
...@@ -3,15 +3,21 @@ ...@@ -3,15 +3,21 @@
@import "bootstrap/variables"; @import "bootstrap/variables";
@import "framework/mixins"; @import "framework/mixins";
.content-wrapper.page-with-new-nav {
margin-top: $new-navbar-height;
}
header.navbar-gitlab-new { header.navbar-gitlab-new {
color: $white-light; color: $white-light;
background: linear-gradient(to right, $indigo-900, $indigo-800); background: linear-gradient(to right, $indigo-900, $indigo-800);
border-bottom: 0; border-bottom: 0;
min-height: $new-navbar-height;
.header-content { .header-content {
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
padding-left: 0; padding-left: 0;
min-height: $new-navbar-height;
.title-container { .title-container {
display: -webkit-flex; display: -webkit-flex;
...@@ -39,20 +45,13 @@ header.navbar-gitlab-new { ...@@ -39,20 +45,13 @@ header.navbar-gitlab-new {
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
align-items: center; align-items: center;
padding-right: $gl-padding; padding: 2px 8px;
padding-left: $gl-padding; margin: 5px 2px 5px -8px;
margin-left: -$gl-padding; border-radius: $border-radius-default;
@media (min-width: $screen-sm-min) {
padding-right: $gl-padding;
padding-left: $gl-padding;
}
svg { svg {
margin-top: -3px;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
margin-right: 10px; margin-right: 8px;
} }
} }
...@@ -61,7 +60,7 @@ header.navbar-gitlab-new { ...@@ -61,7 +60,7 @@ header.navbar-gitlab-new {
svg { svg {
width: 55px; width: 55px;
height: 15px; height: 14px;
margin: 0; margin: 0;
fill: $white-light; fill: $white-light;
} }
...@@ -69,9 +68,7 @@ header.navbar-gitlab-new { ...@@ -69,9 +68,7 @@ header.navbar-gitlab-new {
&:hover, &:hover,
&:focus { &:focus {
.logo-text svg { background-color: rgba($indigo-200, .2);
fill: $tanuki-yellow;
}
} }
} }
} }
...@@ -91,6 +88,20 @@ header.navbar-gitlab-new { ...@@ -91,6 +88,20 @@ header.navbar-gitlab-new {
right: 0; right: 0;
} }
} }
&.menu-expanded {
@media (max-width: $screen-xs-max) {
.title-container,
.header-logo, {
display: none;
}
}
}
}
.dropdown-bold-header {
color: $gl-text-color-secondary;
font-size: 12px;
} }
.navbar-collapse { .navbar-collapse {
...@@ -99,14 +110,10 @@ header.navbar-gitlab-new { ...@@ -99,14 +110,10 @@ header.navbar-gitlab-new {
box-shadow: 0; box-shadow: 0;
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
margin-left: -$gl-padding; margin-left: -8px;
margin-right: -10px; margin-right: -10px;
} }
.dropdown-bold-header {
color: initial;
}
.nav { .nav {
> li:not(.hidden-xs) a { > li:not(.hidden-xs) a {
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
...@@ -120,7 +127,7 @@ header.navbar-gitlab-new { ...@@ -120,7 +127,7 @@ header.navbar-gitlab-new {
.container-fluid { .container-fluid {
.navbar-toggle { .navbar-toggle {
min-width: 45px; min-width: 45px;
padding: 6px $gl-padding; padding: 4px $gl-padding;
margin-right: -7px; margin-right: -7px;
font-size: 14px; font-size: 14px;
text-align: center; text-align: center;
...@@ -157,31 +164,90 @@ header.navbar-gitlab-new { ...@@ -157,31 +164,90 @@ header.navbar-gitlab-new {
} }
> a { > a {
background: none;
will-change: color; will-change: color;
margin: 4px 2px;
padding: 6px 8px;
color: $indigo-200;
height: 32px;
@media (max-width: $screen-xs-max) {
padding: 0;
}
svg {
fill: $indigo-200;
}
&.header-user-dropdown-toggle { &.header-user-dropdown-toggle {
margin-left: 2px;
.header-user-avatar { .header-user-avatar {
border-color: $indigo-200; border-color: $indigo-200;
margin-right: 0;
} }
} }
}
&:hover, .header-new-dropdown-toggle {
&:focus { margin-right: 0;
color: $white-light; }
opacity: 1;
> svg { > a:hover,
fill: $white-light; > a:focus {
} text-decoration: none;
outline: 0;
opacity: 1;
color: $white-light;
@media (min-width: $screen-sm-min) {
background-color: rgba($indigo-200, .2);
}
svg {
fill: currentColor;
}
&.header-user-dropdown-toggle { &.header-user-dropdown-toggle {
.header-user-avatar { .header-user-avatar {
border-color: $white-light; border-color: $white-light;
}
} }
} }
} }
.impersonated-user,
.impersonated-user:hover {
margin-right: 1px;
background-color: $white-light;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
svg {
fill: $indigo-900;
}
}
.impersonation-btn,
.impersonation-btn:hover {
background-color: $white-light;
margin-left: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
i {
color: $orange-500;
font-size: 20px;
}
}
&.active > a,
&.dropdown.open > a {
color: $indigo-900;
background-color: $white-light;
svg {
fill: currentColor;
}
}
} }
} }
} }
...@@ -189,45 +255,76 @@ header.navbar-gitlab-new { ...@@ -189,45 +255,76 @@ header.navbar-gitlab-new {
.navbar-sub-nav { .navbar-sub-nav {
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
margin-bottom: 0; margin: 0 0 0 6px;
color: $indigo-200; color: $indigo-200;
> li { .dropdown-chevron {
> a:hover, position: relative;
> a:focus { top: -1px;
box-shadow: inset 0 -3px 0 rgba($indigo-200, .4); font-size: 10px;
text-decoration: none; }
outline: 0; }
color: $white-light;
}
&.active > a { .navbar-gitlab-new {
box-shadow: inset 0 -3px 0 $indigo-500; .navbar-sub-nav,
color: $white-light; .navbar-nav {
font-weight: $gl-font-weight-bold; > li {
} > a:hover,
> a:focus {
text-decoration: none;
outline: 0;
color: $white-light;
background-color: rgba($indigo-200, .2);
> a { svg {
display: block; fill: currentColor;
padding: 16px 10px; }
font-size: 13px; }
color: currentColor;
box-shadow: inset 0 0 0 transparent;
will-change: box-shadow;
transition: box-shadow 0.15s;
@media (min-width: $screen-sm-min) { &.active > a,
padding: 15px $gl-padding; &.dropdown.open > a {
font-size: 14px; color: $indigo-900;
background-color: $white-light;
svg {
fill: currentColor;
}
}
> a {
display: flex;
align-items: center;
justify-content: center;
padding: 6px 8px;
margin: 4px 2px;
font-size: 12px;
color: currentColor;
border-radius: $border-radius-default;
height: 32px;
font-weight: $gl-font-weight-bold;
svg {
fill: currentColor;
}
}
&.line-separator {
border-left: 1px solid rgba($indigo-200, .2);
margin: 8px;
} }
} }
} }
}
.dropdown-chevron { .admin-icon i {
position: relative; font-size: 18px;
top: -1px; }
font-size: 10px;
} .caret-down {
height: 11px;
width: 11px;
margin-left: 4px;
fill: currentColor;
} }
.header-user .dropdown-menu-nav, .header-user .dropdown-menu-nav,
...@@ -236,10 +333,14 @@ header.navbar-gitlab-new { ...@@ -236,10 +333,14 @@ header.navbar-gitlab-new {
} }
.search { .search {
margin: 4px 8px 0;
form { form {
height: 32px;
border: 0; border: 0;
border-radius: $border-radius-default;
background-color: rgba($indigo-200, .2); background-color: rgba($indigo-200, .2);
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s, background-color ease-in-out 0.15s; transition: border-color ease-in-out 0.15s, background-color ease-in-out 0.15s;
&:hover { &:hover {
background-color: rgba($indigo-200, .3); background-color: rgba($indigo-200, .3);
...@@ -248,31 +349,50 @@ header.navbar-gitlab-new { ...@@ -248,31 +349,50 @@ header.navbar-gitlab-new {
} }
&.search-active form { &.search-active form {
background-color: rgba($indigo-200, .3); background-color: $white-light;
box-shadow: none; box-shadow: none;
.search-input {
color: $gl-text-color;
transition: color ease-in-out 0.15s;
}
.search-input::placeholder {
color: $gl-text-color-tertiary;
}
.search-input-wrap {
.search-icon,
.clear-icon {
color: $gl-text-color-tertiary;
transition: color ease-in-out 0.15s;
}
}
} }
.search-input { .search-input {
color: $white-light; color: $white-light;
background: none; background: none;
transition: color ease-in-out 0.15s;
} }
.search-input::placeholder { .search-input::placeholder {
color: rgba($indigo-200, .8); color: rgba($indigo-200, .8);
transition: color ease-in-out 0.15s;
} }
.location-badge { .location-badge {
font-size: 12px; font-size: 12px;
color: $indigo-100; color: $indigo-100;
background-color: rgba($indigo-200, .1); background-color: rgba($indigo-200, .1);
transition: color 0.15s;
will-change: color; will-change: color;
margin: -4px 4px -4px -4px; margin: -4px 4px -4px -4px;
line-height: 25px; line-height: 25px;
padding: 4px 8px; padding: 4px 8px;
border-radius: 2px 0 0 2px; border-radius: 2px 0 0 2px;
border-right: 1px solid $indigo-800; border-right: 1px solid $indigo-800;
height: 34px; height: 32px;
transition: border-color ease-in-out 0.15s;
} }
.search-input-wrap { .search-input-wrap {
...@@ -284,8 +404,9 @@ header.navbar-gitlab-new { ...@@ -284,8 +404,9 @@ header.navbar-gitlab-new {
&.search-active { &.search-active {
.location-badge { .location-badge {
color: $white-light; color: $gl-text-color;
background-color: rgba($indigo-200, .2); background-color: $nav-badge-bg;
border-color: $border-color;
} }
.search-input-wrap { .search-input-wrap {
...@@ -403,3 +524,14 @@ header.navbar-gitlab-new { ...@@ -403,3 +524,14 @@ header.navbar-gitlab-new {
} }
} }
} }
.btn-sign-in {
margin-top: 3px;
background-color: $indigo-100;
color: $indigo-900;
font-weight: $gl-font-weight-bold;
&:hover {
background-color: $white-light;
}
}
...@@ -26,7 +26,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -26,7 +26,7 @@ $new-sidebar-collapsed-width: 50px;
// Override position: absolute // Override position: absolute
.right-sidebar { .right-sidebar {
position: fixed; position: fixed;
height: calc(100% - #{$header-height}); height: calc(100% - #{$new-navbar-height});
} }
.issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header { .issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
...@@ -92,7 +92,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -92,7 +92,7 @@ $new-sidebar-collapsed-width: 50px;
z-index: 400; z-index: 400;
width: $new-sidebar-width; width: $new-sidebar-width;
transition: left $sidebar-transition-duration; transition: left $sidebar-transition-duration;
top: $header-height; top: $new-navbar-height;
bottom: 0; bottom: 0;
left: 0; left: 0;
background-color: $gray-normal; background-color: $gray-normal;
...@@ -188,7 +188,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -188,7 +188,7 @@ $new-sidebar-collapsed-width: 50px;
} }
.with-performance-bar .nav-sidebar { .with-performance-bar .nav-sidebar {
top: $header-height + $performance-bar-height; top: $new-navbar-height + $performance-bar-height;
} }
.sidebar-sub-level-items { .sidebar-sub-level-items {
...@@ -452,7 +452,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -452,7 +452,7 @@ $new-sidebar-collapsed-width: 50px;
// Make issue boards full-height now that sub-nav is gone // Make issue boards full-height now that sub-nav is gone
.boards-list { .boards-list {
height: calc(100vh - #{$header-height}); height: calc(100vh - #{$new-navbar-height});
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
height: 475px; // Needed for PhantomJS height: 475px; // Needed for PhantomJS
...@@ -463,7 +463,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -463,7 +463,7 @@ $new-sidebar-collapsed-width: 50px;
} }
.with-performance-bar .boards-list { .with-performance-bar .boards-list {
height: calc(100vh - #{$header-height} - #{$performance-bar-height}); height: calc(100vh - #{$new-navbar-height} - #{$performance-bar-height});
} }
......
...@@ -440,6 +440,7 @@ ...@@ -440,6 +440,7 @@
&.right-sidebar { &.right-sidebar {
top: 0; top: 0;
bottom: 0; bottom: 0;
height: 100%;
} }
.issuable-sidebar-header { .issuable-sidebar-header {
......
...@@ -227,6 +227,26 @@ ...@@ -227,6 +227,26 @@
margin-top: 20px; margin-top: 20px;
} }
.prometheus-graph-group {
display: flex;
flex-wrap: wrap;
padding: $gl-padding / 2;
}
.prometheus-graph {
flex: 1 0 auto;
min-width: 450px;
padding: $gl-padding / 2;
h5 {
font-size: 16px;
}
@media (max-width: $screen-sm-max) {
min-width: 100%;
}
}
.prometheus-svg-container { .prometheus-svg-container {
position: relative; position: relative;
height: 0; height: 0;
...@@ -297,9 +317,3 @@ ...@@ -297,9 +317,3 @@
} }
} }
} }
.prometheus-row {
h5 {
font-size: 16px;
}
}
...@@ -190,6 +190,8 @@ input[type="checkbox"]:hover { ...@@ -190,6 +190,8 @@ input[type="checkbox"]:hover {
} }
.search-holder { .search-holder {
@include new-style-dropdown;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
display: -webkit-flex; display: -webkit-flex;
display: flex; display: flex;
......
...@@ -302,10 +302,6 @@ module ApplicationHelper ...@@ -302,10 +302,6 @@ module ApplicationHelper
end end
end end
def show_new_nav?
true
end
def collapsed_sidebar? def collapsed_sidebar?
cookies["sidebar_collapsed"] == "true" cookies["sidebar_collapsed"] == "true"
end end
......
...@@ -86,7 +86,7 @@ module GroupsHelper ...@@ -86,7 +86,7 @@ module GroupsHelper
def group_title_link(group, hidable: false, show_avatar: false) def group_title_link(group, hidable: false, show_avatar: false)
link_to(group_path(group), class: "group-path breadcrumb-item-text js-breadcrumb-item-text #{'hidable' if hidable}") do link_to(group_path(group), class: "group-path breadcrumb-item-text js-breadcrumb-item-text #{'hidable' if hidable}") do
output = output =
if (show_new_nav? && group.try(:avatar_url) || (show_new_nav? && show_avatar)) && !Rails.env.test? if (group.try(:avatar_url) || show_avatar)) && !Rails.env.test?
image_tag(group_icon(group), class: "avatar-tile", width: 15, height: 15) image_tag(group_icon(group), class: "avatar-tile", width: 15, height: 15)
else else
"" ""
......
module NavHelper module NavHelper
def page_with_sidebar_class def page_with_sidebar_class
class_name = page_gutter_class class_name = page_gutter_class
class_name << 'page-with-new-sidebar' if defined?(@new_sidebar) && @new_sidebar class_name << 'page-with-new-sidebar' if defined?(@left_sidebar) && @left_sidebar
class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @new_sidebar class_name << 'page-with-icon-sidebar' if collapsed_sidebar? && @left_sidebar
class_name class_name
end end
...@@ -30,24 +30,15 @@ module NavHelper ...@@ -30,24 +30,15 @@ module NavHelper
end end
end end
def nav_header_class def nav_control_class
class_names = [] "nav-control" if current_user
class_names << 'with-horizontal-nav' if defined?(nav) && nav
class_names
end end
def layout_nav_class def user_dropdown_class
return [] if show_new_nav?
class_names = [] class_names = []
class_names << 'page-with-layout-nav' if defined?(nav) && nav class_names << 'header-user-dropdown-toggle'
class_names << 'page-with-sub-nav' if content_for?(:sub_nav) class_names << 'impersonated-user' if session[:impersonator_id]
class_names class_names
end end
def nav_control_class
"nav-control" if current_user
end
end end
...@@ -4,7 +4,7 @@ module PageLayoutHelper ...@@ -4,7 +4,7 @@ module PageLayoutHelper
@page_title.push(*titles.compact) if titles.any? @page_title.push(*titles.compact) if titles.any?
if show_new_nav? && titles.any? && !defined?(@breadcrumb_title) if titles.any? && !defined?(@breadcrumb_title)
@breadcrumb_title = @page_title.last @breadcrumb_title = @page_title.last
end end
......
...@@ -62,7 +62,7 @@ module ProjectsHelper ...@@ -62,7 +62,7 @@ module ProjectsHelper
project_link = link_to project_path(project), { class: ("project-item-select-holder" unless show_new_nav?) } do project_link = link_to project_path(project), { class: ("project-item-select-holder" unless show_new_nav?) } do
output = output =
if show_new_nav? && project.avatar_url && !Rails.env.test? if project.avatar_url && !Rails.env.test?
project_icon(project, alt: project.name, class: 'avatar-tile', width: 15, height: 15) project_icon(project, alt: project.name, class: 'avatar-tile', width: 15, height: 15)
else else
"" ""
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
# #
module Issuable module Issuable
extend ActiveSupport::Concern extend ActiveSupport::Concern
include Gitlab::SQL::Pattern
include CacheMarkdownField include CacheMarkdownField
include Participable include Participable
include Mentionable include Mentionable
...@@ -122,7 +123,9 @@ module Issuable ...@@ -122,7 +123,9 @@ module Issuable
# #
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def search(query) def search(query)
where(arel_table[:title].matches("%#{query}%")) title = to_fuzzy_arel(:title, query)
where(title)
end end
# Searches for records with a matching title or description. # Searches for records with a matching title or description.
...@@ -133,10 +136,10 @@ module Issuable ...@@ -133,10 +136,10 @@ module Issuable
# #
# Returns an ActiveRecord::Relation. # Returns an ActiveRecord::Relation.
def full_search(query) def full_search(query)
t = arel_table title = to_fuzzy_arel(:title, query)
pattern = "%#{query}%" description = to_fuzzy_arel(:description, query)
where(t[:title].matches(pattern).or(t[:description].matches(pattern))) where(title&.or(description))
end end
def sort(method, excluded_labels: []) def sort(method, excluded_labels: [])
......
...@@ -16,6 +16,7 @@ class Group < Namespace ...@@ -16,6 +16,7 @@ class Group < Namespace
source: :user source: :user
has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent has_many :requesters, -> { where.not(requested_at: nil) }, dependent: :destroy, as: :source, class_name: 'GroupMember' # rubocop:disable Cop/ActiveRecordDependent
has_many :members_and_requesters, as: :source, class_name: 'GroupMember'
has_many :milestones has_many :milestones
has_many :project_group_links, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :project_group_links, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
......
...@@ -126,20 +126,11 @@ class Member < ActiveRecord::Base ...@@ -126,20 +126,11 @@ class Member < ActiveRecord::Base
find_by(invite_token: invite_token) find_by(invite_token: invite_token)
end end
def add_user(source, user, access_level, current_user: nil, expires_at: nil) def add_user(source, user, access_level, existing_members: nil, current_user: nil, expires_at: nil)
user = retrieve_user(user) # `user` can be either a User object, User ID or an email to be invited
member = retrieve_member(source, user, existing_members)
access_level = retrieve_access_level(access_level) access_level = retrieve_access_level(access_level)
# `user` can be either a User object or an email to be invited
member =
if user.is_a?(User)
source.members.find_by(user_id: user.id) ||
source.requesters.find_by(user_id: user.id) ||
source.members.build(user_id: user.id)
else
source.members.build(invite_email: user)
end
return member unless can_update_member?(current_user, member) return member unless can_update_member?(current_user, member)
member.attributes = { member.attributes = {
...@@ -165,17 +156,15 @@ class Member < ActiveRecord::Base ...@@ -165,17 +156,15 @@ class Member < ActiveRecord::Base
def add_users(source, users, access_level, current_user: nil, expires_at: nil) def add_users(source, users, access_level, current_user: nil, expires_at: nil)
return [] unless users.present? return [] unless users.present?
# Collect all user ids into separate array emails, users, existing_members = parse_users_list(source, users)
# so we can use single sql query to get user objects
user_ids = users.select { |user| user =~ /\A\d+\Z/ }
users = users - user_ids + User.where(id: user_ids)
self.transaction do self.transaction do
users.map do |user| (emails + users).map! do |user|
add_user( add_user(
source, source,
user, user,
access_level, access_level,
existing_members: existing_members,
current_user: current_user, current_user: current_user,
expires_at: expires_at expires_at: expires_at
) )
...@@ -189,6 +178,31 @@ class Member < ActiveRecord::Base ...@@ -189,6 +178,31 @@ class Member < ActiveRecord::Base
private private
def parse_users_list(source, list)
emails, user_ids, users = [], [], []
existing_members = {}
list.each do |item|
case item
when User
users << item
when Integer
user_ids << item
when /\A\d+\Z/
user_ids << item.to_i
when Devise.email_regexp
emails << item
end
end
if user_ids.present?
users.concat(User.where(id: user_ids))
existing_members = source.members_and_requesters.where(user_id: user_ids).index_by(&:user_id)
end
[emails, users, existing_members]
end
# This method is used to find users that have been entered into the "Add members" field. # This method is used to find users that have been entered into the "Add members" field.
# These can be the User objects directly, their IDs, their emails, or new emails to be invited. # These can be the User objects directly, their IDs, their emails, or new emails to be invited.
def retrieve_user(user) def retrieve_user(user)
...@@ -197,6 +211,20 @@ class Member < ActiveRecord::Base ...@@ -197,6 +211,20 @@ class Member < ActiveRecord::Base
User.find_by(id: user) || User.find_by(email: user) || user User.find_by(id: user) || User.find_by(email: user) || user
end end
def retrieve_member(source, user, existing_members)
user = retrieve_user(user)
if user.is_a?(User)
if existing_members
existing_members[user.id] || source.members.build(user_id: user.id)
else
source.members_and_requesters.find_or_initialize_by(user_id: user.id)
end
else
source.members.build(invite_email: user)
end
end
def retrieve_access_level(access_level) def retrieve_access_level(access_level)
access_levels.fetch(access_level) { access_level.to_i } access_levels.fetch(access_level) { access_level.to_i }
end end
......
...@@ -144,6 +144,7 @@ class Project < ActiveRecord::Base ...@@ -144,6 +144,7 @@ class Project < ActiveRecord::Base
has_many :requesters, -> { where.not(requested_at: nil) }, has_many :requesters, -> { where.not(requested_at: nil) },
as: :source, class_name: 'ProjectMember', dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent as: :source, class_name: 'ProjectMember', dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_many :members_and_requesters, as: :source, class_name: 'ProjectMember'
has_many :deploy_keys_projects has_many :deploy_keys_projects
has_many :deploy_keys, through: :deploy_keys_projects has_many :deploy_keys, through: :deploy_keys_projects
......
- if show_new_nav? && current_user.can_create_group? - if current_user.can_create_group?
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New group", new_group_path, class: "btn btn-new" = link_to "New group", new_group_path, class: "btn btn-new"
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
= nav_link(page: explore_groups_path) do = nav_link(page: explore_groups_path) do
= link_to explore_groups_path, title: 'Explore public groups' do = link_to explore_groups_path, title: 'Explore public groups' do
Explore public groups Explore public groups
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) } .nav-controls.nav-controls-new-nav
= render 'shared/groups/search_form' = render 'shared/groups/search_form'
= render 'shared/groups/dropdown' = render 'shared/groups/dropdown'
- if current_user.can_create_group? - if current_user.can_create_group?
= link_to "New group", new_group_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}" = link_to "New group", new_group_path, class: "btn btn-new visible-xs"
= content_for :flash_message do = content_for :flash_message do
= render 'shared/project_limit' = render 'shared/project_limit'
- if show_new_nav? && current_user.can_create_project? - if current_user.can_create_project?
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New project", new_project_path, class: 'btn btn-new' = link_to "New project", new_project_path, class: 'btn btn-new'
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
= link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do = link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
Explore projects Explore projects
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) } .nav-controls.nav-controls-new-nav
= render 'shared/projects/search_form' = render 'shared/projects/search_form'
= render 'shared/projects/dropdown' = render 'shared/projects/dropdown'
- if current_user.can_create_project? - if current_user.can_create_project?
= link_to "New project", new_project_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}" = link_to "New project", new_project_path, class: "btn btn-new visible-xs"
- if show_new_nav? && current_user - if current_user
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet" = link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet"
...@@ -10,7 +10,3 @@ ...@@ -10,7 +10,3 @@
= nav_link(page: explore_snippets_path) do = nav_link(page: explore_snippets_path) do
= link_to explore_snippets_path, title: 'Explore snippets', data: {placement: 'right'} do = link_to explore_snippets_path, title: 'Explore snippets', data: {placement: 'right'} do
Explore Snippets Explore Snippets
- if current_user
.nav-controls.hidden-xs{ class: ("hidden-sm hidden-md hidden-lg" if show_new_nav?) }
= link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet"
...@@ -4,15 +4,14 @@ ...@@ -4,15 +4,14 @@
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues") = auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues")
- if show_new_nav? - content_for :breadcrumbs_extra do
- content_for :breadcrumbs_extra do = link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do = icon('rss')
= icon('rss') = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do = link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
= icon('rss') = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
......
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
- page_title "Merge Requests" - page_title "Merge Requests"
- header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id) - header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
- if show_new_nav? - content_for :breadcrumbs_extra do
- content_for :breadcrumbs_extra do = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area .top-area
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
......
...@@ -2,14 +2,13 @@ ...@@ -2,14 +2,13 @@
- page_title 'Milestones' - page_title 'Milestones'
- header_title 'Milestones', dashboard_milestones_path - header_title 'Milestones', dashboard_milestones_path
- if show_new_nav? - content_for :breadcrumbs_extra do
- content_for :breadcrumbs_extra do = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.top-area .top-area
= render 'shared/milestones_filter', counts: @milestone_states = render 'shared/milestones_filter', counts: @milestone_states
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.milestones .milestones
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
= webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'filtered_search' = webpack_bundle_tag 'filtered_search'
- if show_new_nav? && group_issues_exists - if group_issues_exists
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do = link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
= icon('rss') = icon('rss')
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
- if group_issues_exists - if group_issues_exists
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= link_to params.merge(rss_url_options), class: 'btn' do = link_to params.merge(rss_url_options), class: 'btn' do
= icon('rss') = icon('rss')
%span.icon-label %span.icon-label
......
- page_title 'Labels' - page_title 'Labels'
- if show_new_nav? && can?(current_user, :admin_label, @group) - if can?(current_user, :admin_label, @group)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New label", new_group_label_path(@group), class: "btn btn-new" = link_to "New label", new_group_label_path(@group), class: "btn btn-new"
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.nav-text .nav-text
Labels can be applied to issues and merge requests. Group labels are available for any project within the group. Labels can be applied to issues and merge requests. Group labels are available for any project within the group.
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
- if can?(current_user, :admin_label, @group) - if can?(current_user, :admin_label, @group)
= link_to "New label", new_group_label_path(@group), class: "btn btn-new" = link_to "New label", new_group_label_path(@group), class: "btn btn-new"
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
= webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'filtered_search' = webpack_bundle_tag 'filtered_search'
- if show_new_nav? && current_user - if current_user
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
.top-area .top-area
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
- if current_user - if current_user
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
= render 'shared/issuable/search_bar', type: :merge_requests = render 'shared/issuable/search_bar', type: :merge_requests
......
- page_title "Milestones" - page_title "Milestones"
- if show_new_nav? && can?(current_user, :admin_milestones, @group) - if can?(current_user, :admin_milestones, @group)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new" = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
.top-area .top-area
= render 'shared/milestones_filter', counts: @milestone_states = render 'shared/milestones_filter', counts: @milestone_states
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
- if can?(current_user, :admin_milestones, @group) - if can?(current_user, :admin_milestones, @group)
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new" = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
= stylesheet_link_tag "test", media: "all" if Rails.env.test? = stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'performance_bar' if performance_bar_enabled? = stylesheet_link_tag 'performance_bar' if performance_bar_enabled?
- if show_new_nav? // TODO: Combine these 2 stylesheets into application.scss
= stylesheet_link_tag "new_nav", media: "all" = stylesheet_link_tag "new_nav", media: "all"
= stylesheet_link_tag "new_sidebar", media: "all" = stylesheet_link_tag "new_sidebar", media: "all"
= Gon::Base.render_data = Gon::Base.render_data
......
.page-with-sidebar{ class: page_with_sidebar_class } .page-with-sidebar{ class: page_with_sidebar_class }
- if show_new_nav? - if defined?(nav) && nav
- if defined?(nav) && nav = render "layouts/nav/sidebar/#{nav}"
= render "layouts/nav/#{nav}" .content-wrapper.page-with-new-nav
- else .mobile-overlay
- if defined?(nav) && nav
.layout-nav
.container-fluid
= render "layouts/nav/#{nav}"
- if content_for?(:sub_nav)
= yield :sub_nav
.content-wrapper{ class: layout_nav_class }
- if show_new_nav?
.mobile-overlay
.alert-wrapper .alert-wrapper
= render "layouts/broadcast" = render "layouts/broadcast"
- if show_new_nav?
- if content_for?(:new_global_flash)
= yield :new_global_flash
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
= render "layouts/flash"
= yield :flash_message = yield :flash_message
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
= render "layouts/flash"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" } %div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
.content{ id: "content-body" } .content{ id: "content-body" }
= yield = yield
- page_title "Admin Area" - page_title "Admin Area"
- header_title "Admin Area", admin_root_path - header_title "Admin Area", admin_root_path
- if show_new_nav? - nav "admin"
- nav "new_admin_sidebar" - @left_sidebar = true
- @new_sidebar = true
- else
- nav "admin"
= render template: "layouts/application" = render template: "layouts/application"
...@@ -4,10 +4,7 @@ ...@@ -4,10 +4,7 @@
%body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } } %body{ class: @body_class, data: { page: body_data_page, project: "#{@project.path if @project}", group: "#{@group.path if @group}", find_file: find_file_path } }
= render "layouts/init_auto_complete" if @gfm_form = render "layouts/init_auto_complete" if @gfm_form
= render 'peek/bar' = render 'peek/bar'
- if show_new_nav? = render "layouts/header/default"
= render "layouts/header/new"
- else
= render "layouts/header/default", title: header_title
= render 'layouts/page', sidebar: sidebar, nav: nav = render 'layouts/page', sidebar: sidebar, nav: nav
= yield :scripts_body = yield :scripts_body
- page_title @group.name - page_title @group.name
- page_description @group.description unless page_description - page_description @group.description unless page_description
- header_title group_title(@group) unless header_title - header_title group_title(@group) unless header_title
- if show_new_nav? - nav "group"
- nav "new_group_sidebar" - @left_sidebar = true
- @new_sidebar = true
- else
- nav "group"
= render template: "layouts/application" = render template: "layouts/application"
%header.navbar.navbar-gitlab{ class: nav_header_class } %header.navbar.navbar-gitlab.navbar-gitlab-new
.navbar-border
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content %a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid .container-fluid
.header-content .header-content
.dropdown.global-dropdown .title-container
%button.global-dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' } %h1.title
%span.sr-only Toggle navigation = link_to root_path, title: 'Dashboard', id: 'logo' do
= icon('bars') = brand_header_logo
.dropdown-menu-nav.global-dropdown-menu %span.logo-text.hidden-xs
- if current_user = render 'shared/logo_type.svg'
= render 'layouts/nav/dashboard'
- else
= render 'layouts/nav/explore'
.header-logo - if current_user
= link_to root_path, class: 'home', title: 'Dashboard', id: 'logo' do = render "layouts/nav/dashboard"
= brand_header_logo - else
= render "layouts/nav/explore"
.title-container.js-title-container
%h1.title{ class: ('initializing' if @has_group_title) }= title
.navbar-collapse.collapse .navbar-collapse.collapse
%ul.nav.navbar-nav %ul.nav.navbar-nav
- if current_user
= render 'layouts/header/new_dropdown'
%li.hidden-sm.hidden-xs %li.hidden-sm.hidden-xs
= render 'layouts/search' unless current_controller?(:search) = render 'layouts/search' unless current_controller?(:search)
%li.visible-sm-inline-block.visible-xs-inline-block %li.visible-sm-inline-block.visible-xs-inline-block
= link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('search') = icon('search')
- if current_user - if current_user
- if session[:impersonator_id] %li.user-counter
%li.impersonation = link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= link_to admin_impersonation_path, method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('user-secret fw')
- if current_user.admin?
%li
= link_to admin_root_path, title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('wrench fw')
= render 'layouts/header/new_dropdown'
- if Gitlab::Sherlock.enabled?
%li
= link_to sherlock_transactions_path, title: 'Sherlock Transactions',
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('tachometer fw')
%li
= link_to assigned_issues_dashboard_path, title: 'Issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('issues') = custom_icon('issues')
- issues_count = assigned_issuables_count(:issues) - issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) } %span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count) = number_with_delimiter(issues_count)
%li %li.user-counter
= link_to assigned_mrs_dashboard_path, title: 'Merge requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = link_to assigned_mrs_dashboard_path, title: 'Merge requests', class: 'dashboard-shortcuts-merge_requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('mr_bold') = custom_icon('mr_bold')
- merge_requests_count = assigned_issuables_count(:merge_requests) - merge_requests_count = assigned_issuables_count(:merge_requests)
%span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) } %span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
= number_with_delimiter(merge_requests_count) = number_with_delimiter(merge_requests_count)
%li %li.user-counter
= link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do = link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('check-circle fw') = custom_icon('todo_done')
%span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) } %span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
= todos_count_format(todos_pending_count) = todos_count_format(todos_pending_count)
%li.header-user.dropdown %li.header-user.dropdown
= link_to current_user, class: "header-user-dropdown-toggle", data: { toggle: "dropdown" } do = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
= image_tag avatar_icon(current_user, 26), width: 26, height: 26, class: "header-user-avatar" = image_tag avatar_icon(current_user, 23), width: 23, height: 23, class: "header-user-avatar"
= icon('caret-down') = custom_icon('caret_down')
.dropdown-menu-nav.dropdown-menu-align-right .dropdown-menu-nav.dropdown-menu-align-right
%ul %ul
%li.current-user %li.current-user
...@@ -74,18 +56,24 @@ ...@@ -74,18 +56,24 @@
= link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username } = link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
%li %li
= link_to "Settings", profile_path = link_to "Settings", profile_path
- if current_user
%li
= link_to "Help", help_path
%li.divider %li.divider
%li %li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link" = link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
- if session[:impersonator_id]
%li.impersonation
= link_to admin_impersonation_path, class: 'impersonation-btn', method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('user-secret')
- else - else
%li %li
%div %div
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success' = link_to "Sign in / Register", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
%button.navbar-toggle{ type: 'button' } %button.navbar-toggle.hidden-sm.hidden-md.hidden-lg{ type: 'button' }
%span.sr-only Toggle navigation %span.sr-only Toggle navigation
= icon('ellipsis-v') = icon('ellipsis-v', class: 'js-navbar-toggle-right')
= icon('times', class: 'js-navbar-toggle-left')
= yield :header_content
= render 'shared/outdated_browser' = render 'shared/outdated_browser'
%header.navbar.navbar-gitlab.navbar-gitlab-new{ class: nav_header_class }
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
.title-container
%h1.title
= link_to root_path, title: 'Dashboard', id: 'logo' do
= brand_header_logo
%span.logo-text.hidden-xs
= render 'shared/logo_type.svg'
- if current_user
= render "layouts/nav/new_dashboard"
- else
= render "layouts/nav/new_explore"
.navbar-collapse.collapse
%ul.nav.navbar-nav
%li.hidden-sm.hidden-xs
= render 'layouts/search' unless current_controller?(:search)
%li.visible-sm-inline-block.visible-xs-inline-block
= link_to search_path, title: 'Search', aria: { label: "Search" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('search')
- if current_user
- if session[:impersonator_id]
%li.impersonation
= link_to admin_impersonation_path, method: :delete, title: "Stop impersonation", aria: { label: 'Stop impersonation' }, data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('user-secret fw')
- if current_user.admin?
%li
= link_to admin_root_path, title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('wrench fw')
= render 'layouts/header/new_dropdown'
- if Gitlab::Sherlock.enabled?
%li
= link_to sherlock_transactions_path, title: 'Sherlock Transactions',
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('tachometer fw')
%li
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues', aria: { label: "Issues" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('issues')
- issues_count = assigned_issuables_count(:issues)
%span.badge.issues-count{ class: ('hidden' if issues_count.zero?) }
= number_with_delimiter(issues_count)
%li
= link_to assigned_mrs_dashboard_path, title: 'Merge requests', class: 'dashboard-shortcuts-merge_requests', aria: { label: "Merge requests" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= custom_icon('mr_bold')
- merge_requests_count = assigned_issuables_count(:merge_requests)
%span.badge.merge-requests-count{ class: ('hidden' if merge_requests_count.zero?) }
= number_with_delimiter(merge_requests_count)
%li
= link_to dashboard_todos_path, title: 'Todos', aria: { label: "Todos" }, class: 'shortcuts-todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('check-circle fw')
%span.badge.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
= todos_count_format(todos_pending_count)
%li.header-user.dropdown
= link_to current_user, class: "header-user-dropdown-toggle", data: { toggle: "dropdown" } do
= image_tag avatar_icon(current_user, 26), width: 26, height: 26, class: "header-user-avatar"
= icon('chevron-down')
.dropdown-menu-nav.dropdown-menu-align-right
%ul
%li.current-user
.user-name.bold
= current_user.name
@#{current_user.username}
%li.divider
%li
= link_to "Profile", current_user, class: 'profile-link', data: { user: current_user.username }
%li
= link_to "Settings", profile_path
%li.divider
%li
= link_to "Sign out", destroy_user_session_path, method: :delete, class: "sign-out-link"
- else
%li
%div
= link_to "Sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in btn-success'
%button.navbar-toggle.hidden-sm.hidden-md.hidden-lg{ type: 'button' }
%span.sr-only Toggle navigation
= icon('ellipsis-v', class: 'js-navbar-toggle-right')
= icon('times', class: 'js-navbar-toggle-left')
= render 'shared/outdated_browser'
%li.header-new.dropdown %li.header-new.dropdown
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", title: "New...", ref: 'tooltip', aria: { label: "New..." }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body' } do = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", title: "New...", ref: 'tooltip', aria: { label: "New..." }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body' } do
- if show_new_nav? = custom_icon('plus_square')
= icon('plus') = custom_icon('caret_down')
= icon('chevron-down')
- else
= icon('plus fw')
= icon('caret-down')
.dropdown-menu-nav.dropdown-menu-align-right .dropdown-menu-nav.dropdown-menu-align-right
%ul %ul
- if @group&.persisted? - if @group&.persisted?
......
= render 'layouts/nav/admin_settings'
.scrolling-tabs-container{ class: nav_control_class }
.fade-left
= icon('angle-left')
.fade-right
= icon('angle-right')
%ul.nav-links.scrolling-tabs
= nav_link(controller: %w(dashboard admin projects users groups builds runners cohorts), html_options: {class: 'home'}) do
= link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do
%span
Overview
= nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles)) do
= link_to admin_conversational_development_index_path, title: 'Monitoring' do
%span
Monitoring
= nav_link(controller: :broadcast_messages) do
= link_to admin_broadcast_messages_path, title: 'Messages' do
%span
Messages
= nav_link(controller: [:hooks, :hook_logs]) do
= link_to admin_hooks_path, title: 'Hooks' do
%span
System Hooks
= nav_link(controller: :applications) do
= link_to admin_applications_path, title: 'Applications' do
%span
Applications
= nav_link(controller: :abuse_reports) do
= link_to admin_abuse_reports_path, title: "Abuse Reports" do
%span
Abuse Reports
%span.badge.count= number_with_delimiter(AbuseReport.count(:all))
- if akismet_enabled?
= nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path, title: "Spam Logs" do
%span
Spam Logs
.controls
.dropdown.admin-settings-dropdown
%a.dropdown-new.btn.btn-default{ href: '#', 'data-toggle' => 'dropdown' }
= icon('cog')
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-align-right
= nav_link(controller: :deploy_keys) do
= link_to admin_deploy_keys_path, title: 'Deploy Keys' do
%span
Deploy Keys
= nav_link(controller: :services) do
= link_to admin_application_settings_services_path, title: 'Service Templates' do
%span
Service Templates
= nav_link(controller: :labels) do
= link_to admin_labels_path, title: 'Labels' do
%span
Labels
= nav_link(controller: :appearances) do
= link_to admin_appearances_path, title: 'Appearances' do
%span
Appearance
%li.divider
= nav_link(controller: :application_settings) do
= link_to admin_application_settings_path, title: 'Settings' do
%span
Settings
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
- hide_top_links = @hide_top_links || false - hide_top_links = @hide_top_links || false
%nav.breadcrumbs{ role: "navigation", class: [container, @content_class] } %nav.breadcrumbs{ role: "navigation", class: [container, @content_class] }
.breadcrumbs-container .breadcrumbs-container{ class: [container, @content_class] }
- if defined?(@new_sidebar) - if defined?(@left_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do = button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only Open sidebar %span.sr-only Open sidebar
= icon ('bars') = icon ('bars')
......
%ul %ul.list-unstyled.navbar-sub-nav
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do = nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown" }) do
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do %a{ href: "#", data: { toggle: "dropdown" } }
.shortcut-mappings Projects
.key = custom_icon('caret_down')
= icon('arrow-up', 'aria-label' => 'hidden') .dropdown-menu.projects-dropdown-menu
P = render "layouts/nav/projects_dropdown/show"
%span
Projects = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "hidden-xs" }) do
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
.shortcut-mappings
.key
= icon('arrow-up', 'aria-label' => 'hidden')
A
%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, class: 'dashboard-shortcuts-groups', title: 'Groups' do = link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
.shortcut-mappings Groups
.key
= icon('arrow-up', 'aria-label' => 'hidden') = nav_link(path: 'dashboard#activity', html_options: { class: "visible-lg" }) do
G = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
%span Activity
Groups
= nav_link(controller: 'dashboard/milestones') do = nav_link(controller: 'dashboard/milestones', html_options: { class: "visible-lg" }) do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do = link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
.shortcut-mappings Milestones
.key
= icon('arrow-up', 'aria-label' => 'hidden') = nav_link(controller: 'dashboard/snippets', html_options: { class: "visible-lg" }) do
L
%span
Milestones
= nav_link(path: 'dashboard#issues') do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
.shortcut-mappings
.key
= icon('arrow-up', 'aria-label' => 'hidden')
I
%span.badge.pull-right= number_with_delimiter(assigned_issuables_count(:issues))
%span
Issues
= nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
.shortcut-mappings
.key
= icon('arrow-up', 'aria-label' => 'hidden')
M
%span.badge.pull-right= number_with_delimiter(assigned_issuables_count(:merge_requests))
%span
Merge Requests
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do = link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
.shortcut-mappings Snippets
.key
= icon('arrow-up', 'aria-label' => 'hidden') %li.dropdown.hidden-lg
S %a{ href: "#", data: { toggle: "dropdown" } }
%span More
Snippets = custom_icon('caret_down')
%li.divider .dropdown-menu
%li %ul
= link_to "Help", help_path, title: 'About GitLab CE', class: 'about-gitlab' = nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { class: "visible-xs" }) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, title: 'Activity' do
Activity
= nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
-# Shortcut to Dashboard > Projects
%li.hidden
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
- if current_user.admin? || Gitlab::Sherlock.enabled?
%li.line-separator.hidden-xs
- if current_user.admin?
= nav_link(controller: 'admin/dashboard') do
= link_to admin_root_path, class: 'admin-icon', title: 'Admin area', aria: { label: "Admin area" }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('wrench fw')
- if Gitlab::Sherlock.enabled?
%li
= link_to sherlock_transactions_path, class: 'admin-icon', title: 'Sherlock Transactions',
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('tachometer fw')
%ul %ul.list-unstyled.navbar-sub-nav
= nav_link(path: ['dashboard#show', 'root#show', 'projects#trending', 'projects#starred', 'projects#index'], html_options: {class: 'home'}) do = 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', class: 'dashboard-shortcuts-projects' do = link_to explore_root_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
.shortcut-mappings Projects
.key
= icon('arrow-up', 'aria-label' => 'hidden')
P
%span
Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do = link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
.shortcut-mappings Groups
.key
= icon('arrow-up', 'aria-label' => 'hidden')
G
%span
Groups
= nav_link(controller: :snippets) do = nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do = link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
.shortcut-mappings Snippets
.key %li
= icon('arrow-up', 'aria-label' => 'hidden') = link_to "Help", help_path, title: 'About GitLab CE'
S
%span
Snippets
%li.divider
= nav_link(controller: :help) do
= link_to help_path, title: 'Help' do
%span
Help
.scrolling-tabs-container{ class: nav_control_class }
.fade-left
= icon('angle-left')
.fade-right
= icon('angle-right')
%ul.nav-links.scrolling-tabs
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_path(@group), title: 'Home' do
%span
Group
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
= link_to issues_group_path(@group), title: 'Issues' do
%span
Issues
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.badge.count= number_with_delimiter(issues.count)
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
%span
Merge Requests
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
%span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group), title: 'Members' do
%span
Members
- if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do
= link_to edit_group_path(@group), title: 'Settings' do
%span
Settings
%ul.list-unstyled.navbar-sub-nav
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown" }) do
%a{ href: '#', title: 'Projects', data: { toggle: 'dropdown' } }
Projects
= icon("chevron-down", class: "dropdown-chevron")
.dropdown-menu.projects-dropdown-menu
= render "layouts/nav/projects_dropdown/show"
= nav_link(controller: ['dashboard/groups', 'explore/groups']) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
= nav_link(path: 'dashboard#activity', html_options: { class: "hidden-xs hidden-sm hidden-md" }) do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
Activity
%li.dropdown
%a{ href: "#", data: { toggle: "dropdown" } }
More
= icon("chevron-down", class: "dropdown-chevron")
.dropdown-menu
%ul
= nav_link(path: 'dashboard#activity', html_options: { class: "visible-xs visible-sm visible-md" }) do
= link_to activity_dashboard_path, title: 'Activity' do
Activity
= nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, class: 'dashboard-shortcuts-milestones', title: 'Milestones' do
Milestones
= nav_link(controller: 'dashboard/snippets') do
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
Snippets
%li.divider
%li
= link_to "Help", help_path, title: 'About GitLab CE'
-# Shortcut to Dashboard > Projects
%li.hidden
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
%ul.list-unstyled.navbar-sub-nav
= 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', class: 'dashboard-shortcuts-projects' do
Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups', class: 'dashboard-shortcuts-groups' do
Groups
%li.dropdown
%a{ href: "#", data: { toggle: "dropdown" } }
More
= icon("chevron-down", class: "dropdown-chevron")
.dropdown-menu
%ul
= nav_link(controller: :snippets) do
= link_to explore_snippets_path, title: 'Snippets', class: 'dashboard-shortcuts-snippets' do
Snippets
%li.divider
%li
= link_to "Help", help_path, title: 'About GitLab CE'
.scrolling-tabs-container
.fade-left
= icon('angle-left')
.fade-right
= icon('angle-right')
%ul.nav-links.scrolling-tabs
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do
%span
Profile
= nav_link(controller: [:accounts, :two_factor_auths]) do
= link_to profile_account_path, title: 'Account' do
%span
Account
- if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do
= link_to applications_profile_path, title: 'Applications' do
%span
Applications
= nav_link(controller: :chat_names) do
= link_to profile_chat_names_path, title: 'Chat' do
%span
Chat
= nav_link(controller: :personal_access_tokens) do
= link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
%span
Access Tokens
= nav_link(controller: :emails) do
= link_to profile_emails_path, title: 'Emails' do
%span
Emails
- unless current_user.ldap_user?
= nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do
%span
Password
= nav_link(controller: :notifications) do
= link_to profile_notifications_path, title: 'Notifications' do
%span
Notifications
= nav_link(controller: :keys) do
= link_to profile_keys_path, title: 'SSH Keys' do
%span
SSH Keys
= nav_link(controller: :gpg_keys) do
= link_to profile_gpg_keys_path, title: 'GPG Keys' do
%span
GPG Keys
= nav_link(controller: :preferences) do
= link_to profile_preferences_path, title: 'Preferences' do
%span
Preferences
= nav_link(path: 'profiles#audit_log') do
= link_to audit_log_profile_path, title: 'Authentication log' do
%span
Authentication log
- can_edit = can?(current_user, :admin_project, @project)
.scrolling-tabs-container{ class: nav_control_class }
.fade-left
= icon('angle-left')
.fade-right
= icon('angle-right')
%ul.nav-links.scrolling-tabs
= nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
%span
Project
- if project_nav_tab? :files
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
= link_to project_tree_path(@project), title: 'Repository', class: 'shortcuts-tree' do
%span
Repository
- if project_nav_tab? :container_registry
= nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
%span
Registry
- if project_nav_tab? :issues
= nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
= link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do
%span
Issues
- if @project.issues_enabled?
%span.badge.count.issue_counter
= number_with_delimiter(@project.open_issues_count)
- if project_nav_tab? :merge_requests
- controllers = [:merge_requests, 'projects/merge_requests/conflicts']
- controllers.push(:merge_requests, :labels, :milestones) unless @project.issues_enabled?
= nav_link(controller: controllers) do
= link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
%span
Merge Requests
%span.badge.count.merge_counter.js-merge-counter
= number_with_delimiter(@project.open_merge_requests_count)
- if project_nav_tab? :pipelines
= nav_link(controller: [:pipelines, :builds, :environments, :artifacts]) do
= link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
%span
Pipelines
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do
= link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
%span
Wiki
- if project_nav_tab? :snippets
= nav_link(controller: :snippets) do
= link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do
%span
Snippets
- if project_nav_tab? :project_members
= nav_link(controller: :project_members) do
= link_to project_project_members_path(@project), title: 'Members', class: 'shortcuts-members' do
%span
Members
- if project_nav_tab? :settings
= nav_link(path: %w[projects#edit members#show integrations#show services#edit repository#show ci_cd#show pages#show]) do
= link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do
%span
Settings
-# Shortcut to Project > Activity
%li.hidden
= link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
%span
Activity
-# Shortcut to Repository > Graph (formerly, Network)
- if project_nav_tab? :network
%li.hidden
= link_to project_network_path(@project, current_ref), title: 'Network', class: 'shortcuts-network' do
Graph
-# Shortcut to Repository > Charts (formerly, top-nav item "Graphs")
- unless @project.empty_repo?
%li.hidden
= link_to charts_project_graph_path(@project, current_ref), title: 'Charts', class: 'shortcuts-repository-charts' do
Charts
-# Shortcut to Issues > New Issue
%li.hidden
= link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do
Create a new issue
-# Shortcut to Pipelines > Jobs
- if project_nav_tab? :builds
%li.hidden
= link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do
Jobs
-# Shortcut to commits page
- if project_nav_tab? :commits
%li.hidden
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
Commits
-# Shortcut to issue boards
%li.hidden
= link_to 'Issue Boards', project_boards_path(@project), title: 'Issue Boards', class: 'shortcuts-issue-boards'
- page_title "User Settings" - page_title "User Settings"
- header_title "User Settings", profile_path unless header_title - header_title "User Settings", profile_path unless header_title
- sidebar "dashboard" - sidebar "dashboard"
- if show_new_nav? - nav "profile"
- nav "new_profile_sidebar" - @left_sidebar = true
- @new_sidebar = true
- else
- nav "profile"
= render template: "layouts/application" = render template: "layouts/application"
- page_title @project.name_with_namespace - page_title @project.name_with_namespace
- page_description @project.description unless page_description - page_description @project.description unless page_description
- header_title project_title(@project) unless header_title - header_title project_title(@project) unless header_title
- if show_new_nav? - nav "project"
- nav "new_project_sidebar" - @left_sidebar = true
- @new_sidebar = true
- else
- nav "project"
- content_for :project_javascripts do - content_for :project_javascripts do
- project = @target_project || @project - project = @target_project || @project
......
- page_title 'Two-Factor Authentication', 'Account' - page_title 'Two-Factor Authentication', 'Account'
- if show_new_nav? - add_to_breadcrumbs("Account", profile_account_path)
- add_to_breadcrumbs("Account", profile_account_path)
- else
- header_title "Two-Factor Authentication", profile_two_factor_auth_path
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
= render 'profiles/head' = render 'profiles/head'
......
- project = local_assigns.fetch(:project) - project = local_assigns.fetch(:project)
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
= content_for flash_message_container do = content_for :flash_message do
= render partial: 'deletion_failed', locals: { project: project } = render partial: 'deletion_failed', locals: { project: project }
- if current_user && can?(current_user, :download_code, project) - if current_user && can?(current_user, :download_code, project)
= render 'shared/no_ssh' = render 'shared/no_ssh'
......
- @no_container = true - @no_container = true
- page_title "Environments" - page_title "Environments"
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
= render "projects/pipelines/head" = render "projects/pipelines/head"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
......
...@@ -13,15 +13,14 @@ ...@@ -13,15 +13,14 @@
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues") = auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues")
- if show_new_nav? - content_for :breadcrumbs_extra do
- content_for :breadcrumbs_extra do = render "projects/issues/nav_btns"
= render "projects/issues/nav_btns"
- if project_issues(@project).exists? - if project_issues(@project).exists?
%div{ class: (container_class) } %div{ class: (container_class) }
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= render "projects/issues/nav_btns" = render "projects/issues/nav_btns"
= render 'shared/issuable/search_bar', type: :issues = render 'shared/issuable/search_bar', type: :issues
......
...@@ -39,8 +39,7 @@ ...@@ -39,8 +39,7 @@
%ul %ul
- if can_update_issue - if can_update_issue
%li= link_to 'Edit', edit_project_issue_path(@project, @issue) %li= link_to 'Edit', edit_project_issue_path(@project, @issue)
/ TODO: simplify condition back #36860 - unless current_user == @issue.author
- if @issue.author && current_user != @issue.author
%li= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue)) %li= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue))
- if can_update_issue - if can_update_issue
%li= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "btn-close js-btn-issue-action #{issue_button_visibility(@issue, true)}", title: 'Close issue' %li= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "btn-close js-btn-issue-action #{issue_button_visibility(@issue, true)}", title: 'Close issue'
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- hide_class = '' - hide_class = ''
- can_admin_label = can?(current_user, :admin_label, @project) - can_admin_label = can?(current_user, :admin_label, @project)
- if show_new_nav? && can?(current_user, :admin_label, @project) - if can?(current_user, :admin_label, @project)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New label", new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new" = link_to "New label", new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new"
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging. Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
- if can_admin_label - if can_admin_label
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= link_to new_project_label_path(@project), class: "btn btn-new" do = link_to new_project_label_path(@project), class: "btn btn-new" do
New label New label
......
...@@ -12,9 +12,8 @@ ...@@ -12,9 +12,8 @@
= webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'filtered_search' = webpack_bundle_tag 'filtered_search'
- if show_new_nav? - content_for :breadcrumbs_extra do
- 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/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path
= render 'projects/last_push' = render 'projects/last_push'
...@@ -22,7 +21,7 @@ ...@@ -22,7 +21,7 @@
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= render "projects/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path = 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 = render 'shared/issuable/search_bar', type: :merge_requests
......
- @no_container = true - @no_container = true
- page_title 'Milestones' - page_title 'Milestones'
- if show_new_nav? && can?(current_user, :admin_milestone, @project) - if can?(current_user, :admin_milestone, @project)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New milestone", new_namespace_project_milestone_path(@project.namespace, @project), class: 'btn btn-new', title: 'New milestone' = link_to "New milestone", new_namespace_project_milestone_path(@project.namespace, @project), class: 'btn btn-new', title: 'New milestone'
...@@ -11,10 +11,10 @@ ...@@ -11,10 +11,10 @@
.top-area .top-area
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones) = render 'shared/milestones_filter', counts: milestone_counts(@project.milestones)
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) } .nav-controls.nav-controls-new-nav
= render 'shared/milestones_sort_dropdown' = render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @project) - if can?(current_user, :admin_milestone, @project)
= link_to new_project_milestone_path(@project), class: "btn btn-new #{("visible-xs" if show_new_nav?)}", title: 'New milestone' do = link_to new_project_milestone_path(@project), class: "btn btn-new visible-xs", title: 'New milestone' do
New milestone New milestone
.milestones .milestones
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
- @no_container = true - @no_container = true
- page_title _("Pipeline Schedules") - page_title _("Pipeline Schedules")
- if show_new_nav? && can?(current_user, :create_pipeline_schedule, @project) - if can?(current_user, :create_pipeline_schedule, @project)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to _('New schedule'), new_namespace_project_pipeline_schedule_path(@project.namespace, @project), class: 'btn btn-create' = link_to _('New schedule'), new_namespace_project_pipeline_schedule_path(@project.namespace, @project), class: 'btn btn-create'
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
= render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
- if can?(current_user, :create_pipeline_schedule, @project) - if can?(current_user, :create_pipeline_schedule, @project)
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
= link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do
%span= _('New schedule') %span= _('New schedule')
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
- @breadcrumb_link = namespace_project_pipeline_schedules_path(@project.namespace, @project) - @breadcrumb_link = namespace_project_pipeline_schedules_path(@project.namespace, @project)
- page_title _("New Pipeline Schedule") - page_title _("New Pipeline Schedule")
- if show_new_nav? - add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
%h3.page-title %h3.page-title
= _("Schedule a new pipeline") = _("Schedule a new pipeline")
......
...@@ -60,8 +60,21 @@ ...@@ -60,8 +60,21 @@
= f.check_box :public_builds = f.check_box :public_builds
%strong Public pipelines %strong Public pipelines
.help-block .help-block
Allow everyone to access pipelines for public and internal projects Allow public access to pipelines and job details, including output logs and artifacts
= link_to icon('question-circle'), help_page_path('user/project/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank' = link_to icon('question-circle'), help_page_path('user/project/pipelines/settings', anchor: 'visibility-of-pipelines'), target: '_blank'
.bs-callout.bs-callout-info
%p If enabled:
%ul
%li
For public projects, anyone can view pipelines and access job details (output logs and artifacts)
%li
For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)
%li
For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)
%p
If disabled, the access level will depend on the user's
permissions in the project.
%hr %hr
.form-group .form-group
.checkbox .checkbox
......
- breadcrumb_title "Integrations" - breadcrumb_title "Integrations"
- page_title @service.title, "Services" - page_title @service.title, "Services"
- add_to_breadcrumbs("Settings", edit_project_path(@project))
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
= render "projects/settings/head" = render "projects/settings/head"
= render 'form' = render 'form'
- page_title "Snippets" - page_title "Snippets"
- if show_new_nav? && can?(current_user, :create_project_snippet, @project) - if can?(current_user, :create_project_snippet, @project)
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to "New snippet", new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New snippet" = link_to "New snippet", new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New snippet"
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
- include_private = @project.team.member?(current_user) || current_user.admin? - include_private = @project.team.member?(current_user) || current_user.admin?
= render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private } = render partial: 'snippets/snippets_scope_menu', locals: { subject: @project, include_private: include_private }
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls.visible-xs
- if can?(current_user, :create_project_snippet, @project) - if can?(current_user, :create_project_snippet, @project)
= link_to "New snippet", new_project_snippet_path(@project), class: "btn btn-new", title: "New snippet" = link_to "New snippet", new_project_snippet_path(@project), class: "btn btn-new", title: "New snippet"
......
- @no_container = true - @no_container = true
- @sort ||= sort_value_recently_updated - @sort ||= sort_value_recently_updated
- page_title "Tags" - page_title "Tags"
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render "projects/commits/head" = render "projects/commits/head"
.flex-list{ class: container_class } .flex-list{ class: container_class }
......
<svg width="28" height="28" class="tanuki-logo" viewBox="0 0 36 36"> <svg width="24" height="24" class="tanuki-logo" viewBox="0 0 36 36">
<path class="tanuki-shape tanuki-left-ear" fill="#e24329" d="M2 14l9.38 9v-9l-4-12.28c-.205-.632-1.176-.632-1.38 0z"/> <path class="tanuki-shape tanuki-left-ear" fill="#e24329" d="M2 14l9.38 9v-9l-4-12.28c-.205-.632-1.176-.632-1.38 0z"/>
<path class="tanuki-shape tanuki-right-ear" fill="#e24329" d="M34 14l-9.38 9v-9l4-12.28c.205-.632 1.176-.632 1.38 0z"/> <path class="tanuki-shape tanuki-right-ear" fill="#e24329" d="M34 14l-9.38 9v-9l4-12.28c.205-.632 1.176-.632 1.38 0z"/>
<path class="tanuki-shape tanuki-nose" fill="#e24329" d="M18,34.38 3,14 33,14 Z"/> <path class="tanuki-shape tanuki-nose" fill="#e24329" d="M18,34.38 3,14 33,14 Z"/>
......
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" class="caret-down" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 10.243l-4.95-4.95a1 1 0 0 0-1.414 1.414l5.657 5.657a.997.997 0 0 0 1.414 0l5.657-5.657a1 1 0 0 0-1.414-1.414L8 10.243z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m5 5.563v4.875c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-4.875c-1.024-.4-1.75-1.397-1.75-2.563 0-1.519 1.231-2.75 2.75-2.75 1.519 0 2.75 1.231 2.75 2.75 0 1.166-.726 2.162-1.75 2.563m-1 8.687c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25m0-10c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/><path d="m10.501 2c1.381.001 2.499 1.125 2.499 2.506v5.931c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-5.931c0-.279-.225-.506-.499-.506v.926c0 .346-.244.474-.569.271l-2.952-1.844c-.314-.196-.325-.507 0-.71l2.952-1.844c.314-.196.569-.081.569.271v.93m1.499 12.25c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/></svg> <svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 16 16"><path d="m5 5.563v4.875c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-4.875c-1.024-.4-1.75-1.397-1.75-2.563 0-1.519 1.231-2.75 2.75-2.75 1.519 0 2.75 1.231 2.75 2.75 0 1.166-.726 2.162-1.75 2.563m-1 8.687c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25m0-10c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/><path d="m10.501 2c1.381.001 2.499 1.125 2.499 2.506v5.931c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-5.931c0-.279-.225-.506-.499-.506v.926c0 .346-.244.474-.569.271l-2.952-1.844c-.314-.196-.325-.507 0-.71l2.952-1.844c.314-.196.569-.081.569.271v.93m1.499 12.25c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M9 7V4c0-.552-.448-1-1-1s-1 .448-1 1v3H4c-.552 0-1 .448-1 1s.448 1 1 1h3v3c0 .552.448 1 1 1s1-.448 1-1V9h3c.552 0 1-.448 1-1s-.448-1-1-1H9zM3 0h10c1.657 0 3 1.343 3 3v10c0 1.657-1.343 3-3 3H3c-1.657 0-3-1.343-3-3V3c0-1.657 1.343-3 3-3z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8.243 7.485l4.95-4.95a1 1 0 1 1 1.414 1.415L8.95 9.607a.997.997 0 0 1-1.414 0l-2.83-2.83a1 1 0 0 1 1.415-1.413l2.123 2.12zM12 11a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></svg>
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
class: "hidden-xs hidden-sm btn btn-grouped btn-reopen js-btn-issue-action #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}" class: "hidden-xs hidden-sm btn btn-grouped btn-reopen js-btn-issue-action #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}"
- elsif can_update && !is_current_user - elsif can_update && !is_current_user
= render 'shared/issuable/close_reopen_report_toggle', issuable: issuable = render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
- elsif issuable.author - else
/ TODO: change back to else #36860
= link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)), = link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
class: 'hidden-xs hidden-sm btn btn-grouped btn-close-color', title: 'Report abuse' class: 'hidden-xs hidden-sm btn btn-grouped btn-close-color', title: 'Report abuse'
...@@ -37,15 +37,13 @@ ...@@ -37,15 +37,13 @@
%li.divider.droplab-item-ignore %li.divider.droplab-item-ignore
/ TODO: remove condition #36860 %li.report-item{ data: { text: 'Report abuse', url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
- if issuable.author button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
%li.report-item{ data: { text: 'Report abuse', url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)), %button.btn.btn-transparent
button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } } = icon('check', class: 'icon')
%button.btn.btn-transparent .description
= icon('check', class: 'icon') %strong.title Report abuse
.description %p.text
%strong.title Report abuse Report
%p.text = display_issuable_type.pluralize
Report that are abusive, inappropriate or spam.
= display_issuable_type.pluralize
that are abusive, inappropriate or spam.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sidebar') = page_specific_javascript_bundle_tag('sidebar')
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { "offset-top" => ("50" unless show_new_nav?), "spy" => ("affix" unless show_new_nav?), signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } %aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } } .issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } }
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.block.issuable-sidebar-header .block.issuable-sidebar-header
......
---
title: Update gpg documentation with gpg2
merge_request: 13851
author: M M Arif
type: other
---
title: Migrate issues authored by deleted user to the Ghost user
merge_request:
author:
type: fixed
---
title: 'API: Add GPG key management'
merge_request: 13828
author: Robert Schilling
type: added
---
title: Support a multi-word fuzzy seach issues/merge requests on search bar
merge_request: 13780
author: Hiroyuki Sato
type: changed
---
title: Bump jira-ruby gem to 1.4.1 to fix issues with HTTP proxies
merge_request:
author:
type: fixed
class MigrateIssuesToGhostUser < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
class User < ActiveRecord::Base
self.table_name = 'users'
end
class Issue < ActiveRecord::Base
self.table_name = 'issues'
include ::EachBatch
end
def reset_column_in_migration_models
ActiveRecord::Base.clear_cache!
::User.reset_column_information
end
def up
reset_column_in_migration_models
# we use the model method because rewriting it is too complicated and would require copying multiple methods
ghost_id = ::User.ghost.id
Issue.where('NOT EXISTS (?)', User.unscoped.select(1).where('issues.author_id = users.id')).each_batch do |relation|
relation.update_all(author_id: ghost_id)
end
end
def down
end
end
class AddForeignKeyToIssueAuthor < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key(:issues, :users, column: :author_id, on_delete: :nullify)
end
def down
remove_foreign_key(:issues, column: :author_id)
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170831195038) do ActiveRecord::Schema.define(version: 20170901071411) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -1708,6 +1708,7 @@ ActiveRecord::Schema.define(version: 20170831195038) do ...@@ -1708,6 +1708,7 @@ ActiveRecord::Schema.define(version: 20170831195038) do
add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade
add_foreign_key "issue_metrics", "issues", on_delete: :cascade add_foreign_key "issue_metrics", "issues", on_delete: :cascade
add_foreign_key "issues", "projects", name: "fk_899c8f3231", on_delete: :cascade add_foreign_key "issues", "projects", name: "fk_899c8f3231", on_delete: :cascade
add_foreign_key "issues", "users", column: "author_id", name: "fk_05f1e72feb", on_delete: :cascade
add_foreign_key "label_priorities", "labels", on_delete: :cascade add_foreign_key "label_priorities", "labels", on_delete: :cascade
add_foreign_key "label_priorities", "projects", on_delete: :cascade add_foreign_key "label_priorities", "projects", on_delete: :cascade
add_foreign_key "labels", "namespaces", column: "group_id", on_delete: :cascade add_foreign_key "labels", "namespaces", column: "group_id", on_delete: :cascade
......
...@@ -61,16 +61,7 @@ following locations: ...@@ -61,16 +61,7 @@ following locations:
## Road to GraphQL ## Road to GraphQL
Going forward, we will start on moving to We have changed our plans to move to GraphQL. After reviewing the GraphQL license, anything related to the Facebook BSD plus patent license will not be allowed at GitLab.
[GraphQL](http://graphql.org/learn/best-practices/) and deprecate the use of
controller-specific endpoints. GraphQL has a number of benefits:
1. We avoid having to maintain two different APIs.
2. Callers of the API can request only what they need.
3. It is versioned by default.
It will co-exist with the current v4 REST API. If we have a v5 API, this should
be a compatibility layer on top of GraphQL.
## Basic usage ## Basic usage
...@@ -246,8 +237,8 @@ The following table gives an overview of how the API functions generally behave. ...@@ -246,8 +237,8 @@ The following table gives an overview of how the API functions generally behave.
| ------------ | ----------- | | ------------ | ----------- |
| `GET` | Access one or more resources and return the result as JSON. | | `GET` | Access one or more resources and return the result as JSON. |
| `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. | | `POST` | Return `201 Created` if the resource is successfully created and return the newly created resource as JSON. |
| `GET` / `PUT` / `DELETE` | Return `200 OK` if the resource is accessed, modified or deleted successfully. The (modified) result is returned as JSON. | | `GET` / `PUT` | Return `200 OK` if the resource is accessed or modified successfully. The (modified) result is returned as JSON. |
| `DELETE` | Designed to be idempotent, meaning a request to a resource still returns `200 OK` even it was deleted before or is not available. The reasoning behind this, is that the user is not really interested if the resource existed before or not. | | `DELETE` | Returns `204 No Content` if the resuource was deleted successfully. |
The following table shows the possible return codes for API requests. The following table shows the possible return codes for API requests.
......
...@@ -94,7 +94,7 @@ Example response: ...@@ -94,7 +94,7 @@ Example response:
## Delete an environment ## Delete an environment
It returns `200` if the environment was successfully deleted, and `404` if the environment does not exist. It returns `204` if the environment was successfully deleted, and `404` if the environment does not exist.
``` ```
DELETE /projects/:id/environments/:environment_id DELETE /projects/:id/environments/:environment_id
......
...@@ -95,8 +95,7 @@ Parameters: ...@@ -95,8 +95,7 @@ Parameters:
## Delete snippet ## Delete snippet
Deletes an existing project snippet. This is an idempotent function and deleting a non-existent Deletes an existing project snippet. This returns a `204 No Content` status code if the operation was successfully or `404` if the resource was not found.
snippet still returns a `200 OK` status code.
``` ```
DELETE /projects/:id/snippets/:snippet_id DELETE /projects/:id/snippets/:snippet_id
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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