Merge remote-tracking branch 'upstream/master' into 30634-protected-pipeline
* upstream/master: (130 commits) Change auto-retry count to a correct value in docs Fix background migration cleanup specs Fix CI/CD job auto-retry specs Fix JS; make buttons sr accessibile; fix overlay remove redundant changelog entries Merge branch '24570-use-re2-for-user-supplied-regexp-9-3' into 'security-9-3' Merge branch '33303-404-for-unauthorized-project' into 'security-9-3' Merge branch '33359-pers-snippet-files-location' into 'security-9-3' Merge branch 'bvl-remove-appearance-symlink' into 'security-9-3' Hide description about protected branches to non-member Update CHANGELOG.md for 9.0.11 Update CHANGELOG.md for 9.1.8 Update CHANGELOG.md for 8.17.7 Update CHANGELOG.md for 9.2.8 Update CHANGELOG.md for 9.3.8 Respect blockquote line breaks in markdown 35209 Add wip message to new navigation preference section Add github imported projects count to usage data Add versions to Prometheus metrics doc Add Bulgarian translations of Pipeline Schedules ...
This commit is contained in:
commit
43aa8866bc
|
@ -160,6 +160,9 @@ build-package:
|
|||
when: manual
|
||||
script:
|
||||
- scripts/trigger-build
|
||||
only:
|
||||
- //@gitlab-org/gitlab-ce
|
||||
- //@gitlab-org/gitlab-ee
|
||||
|
||||
# Prepare and merge knapsack tests
|
||||
knapsack:
|
||||
|
@ -180,6 +183,7 @@ update-knapsack:
|
|||
<<: *only-canonical-masters
|
||||
stage: post-test
|
||||
script:
|
||||
- retry gem install fog-aws mime-types
|
||||
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
|
||||
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json
|
||||
- '[[ -z ${KNAPSACK_S3_BUCKET} ]] || scripts/sync-reports put $KNAPSACK_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
|
||||
|
|
37
CHANGELOG.md
37
CHANGELOG.md
|
@ -2,6 +2,18 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 9.3.8 (2017-07-19)
|
||||
|
||||
- Improve support for external issue references. !12485
|
||||
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||
- Use uploads/system directory for personal snippets.
|
||||
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||
|
||||
## 9.3.7 (2017-07-18)
|
||||
|
||||
- Prevent bad data being added to application settings when Redis is unavailable. !12750
|
||||
- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
|
||||
|
||||
## 9.3.6 (2017-07-12)
|
||||
|
||||
- Fix API Scoping. !12300
|
||||
|
@ -258,6 +270,13 @@ entry.
|
|||
- Remove foreigh key on ci_trigger_schedules only if it exists.
|
||||
- Allow translation of Pipeline Schedules.
|
||||
|
||||
## 9.2.8 (2017-07-19)
|
||||
|
||||
- Improve support for external issue references. !12485
|
||||
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||
- Fix incorrect project authorizations.
|
||||
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||
|
||||
## 9.2.7 (2017-06-21)
|
||||
|
||||
- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
|
||||
|
@ -502,6 +521,13 @@ entry.
|
|||
- Fix preemptive scroll bar on user activity calendar.
|
||||
- Pipeline chat notifications convert seconds to minutes and hours.
|
||||
|
||||
## 9.1.8 (2017-07-19)
|
||||
|
||||
- Improve support for external issue references. !12485
|
||||
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||
- Fix incorrect project authorizations.
|
||||
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||
|
||||
## 9.1.7 (2017-06-07)
|
||||
|
||||
- No changes.
|
||||
|
@ -814,6 +840,12 @@ entry.
|
|||
- Only send chat notifications for the default branch.
|
||||
- Don't fill in the default kubernetes namespace.
|
||||
|
||||
## 9.0.11 (2017-07-19)
|
||||
|
||||
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||
- Fix incorrect project authorizations.
|
||||
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||
|
||||
## 9.0.10 (2017-06-07)
|
||||
|
||||
- No changes.
|
||||
|
@ -1184,6 +1216,11 @@ entry.
|
|||
- Change development tanuki favicon colors to match logo color order.
|
||||
- API issues - support filtering by iids.
|
||||
|
||||
## 8.17.7 (2017-07-19)
|
||||
|
||||
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||
- Fix incorrect project authorizations.
|
||||
|
||||
## 8.17.6 (2017-05-05)
|
||||
|
||||
- Enforce project features when searching blobs and wikis.
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.17.0
|
||||
0.21.2
|
||||
|
|
12
Gemfile
12
Gemfile
|
@ -37,7 +37,7 @@ gem 'omniauth-saml', '~> 1.7.0'
|
|||
gem 'omniauth-shibboleth', '~> 1.2.0'
|
||||
gem 'omniauth-twitter', '~> 1.2.0'
|
||||
gem 'omniauth_crowd', '~> 2.2.0'
|
||||
gem 'omniauth-authentiq', '~> 0.3.0'
|
||||
gem 'omniauth-authentiq', '~> 0.3.1'
|
||||
gem 'rack-oauth2', '~> 1.2.1'
|
||||
gem 'jwt', '~> 1.5.6'
|
||||
|
||||
|
@ -163,6 +163,9 @@ gem 'rainbow', '~> 2.2'
|
|||
# GitLab settings
|
||||
gem 'settingslogic', '~> 2.0.9'
|
||||
|
||||
# Linear-time regex library for untrusted regular expressions
|
||||
gem 're2', '~> 1.0.0'
|
||||
|
||||
# Misc
|
||||
|
||||
gem 'version_sorter', '~> 2.1.0'
|
||||
|
@ -268,7 +271,7 @@ gem 'peek', '~> 1.0.1'
|
|||
gem 'peek-gc', '~> 0.0.2'
|
||||
gem 'peek-host', '~> 1.0.0'
|
||||
gem 'peek-mysql2', '~> 1.1.0', group: :mysql
|
||||
gem 'peek-performance_bar', '~> 1.2.1'
|
||||
gem 'peek-performance_bar', '~> 1.3.0'
|
||||
gem 'peek-pg', '~> 1.3.0', group: :postgres
|
||||
gem 'peek-rblineprof', '~> 0.2.0'
|
||||
gem 'peek-redis', '~> 1.2.0'
|
||||
|
@ -281,7 +284,7 @@ group :metrics do
|
|||
gem 'influxdb', '~> 0.2', require: false
|
||||
|
||||
# Prometheus
|
||||
gem 'prometheus-client-mmap', '~>0.7.0.beta5'
|
||||
gem 'prometheus-client-mmap', '~>0.7.0.beta9'
|
||||
gem 'raindrops', '~> 0.18'
|
||||
end
|
||||
|
||||
|
@ -390,3 +393,6 @@ gem 'toml-rb', '~> 0.3.15', require: false
|
|||
# Feature toggles
|
||||
gem 'flipper', '~> 0.10.2'
|
||||
gem 'flipper-active_record', '~> 0.10.2'
|
||||
|
||||
# Structured logging
|
||||
gem 'lograge', '~> 0.5'
|
||||
|
|
19
Gemfile.lock
19
Gemfile.lock
|
@ -443,6 +443,10 @@ GEM
|
|||
logging (2.2.2)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.10)
|
||||
lograge (0.5.1)
|
||||
actionpack (>= 4, < 5.2)
|
||||
activesupport (>= 4, < 5.2)
|
||||
railties (>= 4, < 5.2)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.5)
|
||||
|
@ -484,7 +488,7 @@ GEM
|
|||
rack (>= 1.0, < 3)
|
||||
omniauth-auth0 (1.4.1)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-authentiq (0.3.0)
|
||||
omniauth-authentiq (0.3.1)
|
||||
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||
omniauth-azure-oauth2 (0.0.6)
|
||||
jwt (~> 1.0)
|
||||
|
@ -553,7 +557,7 @@ GEM
|
|||
atomic (>= 1.0.0)
|
||||
mysql2
|
||||
peek
|
||||
peek-performance_bar (1.2.1)
|
||||
peek-performance_bar (1.3.0)
|
||||
peek (>= 0.1.0)
|
||||
peek-pg (1.3.0)
|
||||
concurrent-ruby
|
||||
|
@ -588,7 +592,7 @@ GEM
|
|||
premailer-rails (1.9.7)
|
||||
actionmailer (>= 3, < 6)
|
||||
premailer (~> 1.7, >= 1.7.9)
|
||||
prometheus-client-mmap (0.7.0.beta8)
|
||||
prometheus-client-mmap (0.7.0.beta9)
|
||||
mmap2 (~> 2.2, >= 2.2.7)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
|
@ -653,6 +657,7 @@ GEM
|
|||
debugger-ruby_core_source (~> 1.3)
|
||||
rdoc (4.2.2)
|
||||
json (~> 1.4)
|
||||
re2 (1.0.0)
|
||||
recaptcha (3.0.0)
|
||||
json
|
||||
recursive-open-struct (1.0.0)
|
||||
|
@ -998,6 +1003,7 @@ DEPENDENCIES
|
|||
letter_opener_web (~> 1.3.0)
|
||||
license_finder (~> 2.1.0)
|
||||
licensee (~> 8.7.0)
|
||||
lograge (~> 0.5)
|
||||
loofah (~> 2.0.3)
|
||||
mail_room (~> 0.9.1)
|
||||
method_source (~> 0.8)
|
||||
|
@ -1010,7 +1016,7 @@ DEPENDENCIES
|
|||
oj (~> 2.17.4)
|
||||
omniauth (~> 1.4.2)
|
||||
omniauth-auth0 (~> 1.4.1)
|
||||
omniauth-authentiq (~> 0.3.0)
|
||||
omniauth-authentiq (~> 0.3.1)
|
||||
omniauth-azure-oauth2 (~> 0.0.6)
|
||||
omniauth-cas3 (~> 1.1.2)
|
||||
omniauth-facebook (~> 4.0.0)
|
||||
|
@ -1029,7 +1035,7 @@ DEPENDENCIES
|
|||
peek-gc (~> 0.0.2)
|
||||
peek-host (~> 1.0.0)
|
||||
peek-mysql2 (~> 1.1.0)
|
||||
peek-performance_bar (~> 1.2.1)
|
||||
peek-performance_bar (~> 1.3.0)
|
||||
peek-pg (~> 1.3.0)
|
||||
peek-rblineprof (~> 0.2.0)
|
||||
peek-redis (~> 1.2.0)
|
||||
|
@ -1037,7 +1043,7 @@ DEPENDENCIES
|
|||
pg (~> 0.18.2)
|
||||
poltergeist (~> 1.9.0)
|
||||
premailer-rails (~> 1.9.7)
|
||||
prometheus-client-mmap (~> 0.7.0.beta5)
|
||||
prometheus-client-mmap (~> 0.7.0.beta9)
|
||||
pry-byebug (~> 3.4.1)
|
||||
pry-rails (~> 0.3.4)
|
||||
rack-attack (~> 4.4.1)
|
||||
|
@ -1051,6 +1057,7 @@ DEPENDENCIES
|
|||
raindrops (~> 0.18)
|
||||
rblineprof (~> 0.3.6)
|
||||
rdoc (~> 4.2)
|
||||
re2 (~> 1.0.0)
|
||||
recaptcha (~> 3.0)
|
||||
redcarpet (~> 3.4)
|
||||
redis (~> 3.2)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
|
||||
/* global ProjectSelect */
|
||||
/* global ShortcutsNavigation */
|
||||
/* global IssuableIndex */
|
||||
/* global ShortcutsIssuable */
|
||||
|
@ -157,6 +158,9 @@ import PerformanceBar from './performance_bar';
|
|||
shortcut_handler = new ShortcutsIssuable();
|
||||
new ZenMode();
|
||||
break;
|
||||
case 'dashboard:milestones:index':
|
||||
new ProjectSelect();
|
||||
break;
|
||||
case 'projects:milestones:show':
|
||||
case 'groups:milestones:show':
|
||||
case 'dashboard:milestones:show':
|
||||
|
@ -166,6 +170,7 @@ import PerformanceBar from './performance_bar';
|
|||
case 'groups:issues':
|
||||
case 'groups:merge_requests':
|
||||
new UsersSelect();
|
||||
new ProjectSelect();
|
||||
break;
|
||||
case 'dashboard:todos:index':
|
||||
new Todos();
|
||||
|
@ -259,6 +264,7 @@ import PerformanceBar from './performance_bar';
|
|||
break;
|
||||
case 'dashboard:issues':
|
||||
case 'dashboard:merge_requests':
|
||||
new ProjectSelect();
|
||||
new UsersSelect();
|
||||
break;
|
||||
case 'projects:commit:show':
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
/* global dateFormat */
|
||||
/* global Pikaday */
|
||||
|
||||
import DateFix from './lib/utils/datefix';
|
||||
|
||||
class DueDateSelect {
|
||||
constructor({ $dropdown, $loading } = {}) {
|
||||
const $dropdownParent = $dropdown.closest('.dropdown');
|
||||
|
@ -43,14 +45,13 @@ class DueDateSelect {
|
|||
|
||||
initDatePicker() {
|
||||
const $dueDateInput = $(`input[name='${this.fieldName}']`);
|
||||
|
||||
const dateFix = DateFix.dashedFix($dueDateInput.val());
|
||||
const calendar = new Pikaday({
|
||||
field: $dueDateInput.get(0),
|
||||
theme: 'gitlab-theme',
|
||||
format: 'yyyy-mm-dd',
|
||||
onSelect: (dateText) => {
|
||||
const formattedDate = dateFormat(new Date(dateText), 'yyyy-mm-dd');
|
||||
|
||||
$dueDateInput.val(formattedDate);
|
||||
|
||||
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
|
||||
|
@ -62,7 +63,7 @@ class DueDateSelect {
|
|||
}
|
||||
});
|
||||
|
||||
calendar.setDate(new Date($dueDateInput.val()));
|
||||
calendar.setDate(dateFix);
|
||||
this.$datePicker.append(calendar.el);
|
||||
this.$datePicker.data('pikaday', calendar);
|
||||
}
|
||||
|
@ -168,6 +169,7 @@ class DueDateSelectors {
|
|||
initMilestoneDatePicker() {
|
||||
$('.datepicker').each(function() {
|
||||
const $datePicker = $(this);
|
||||
const dateFix = DateFix.dashedFix($datePicker.val());
|
||||
const calendar = new Pikaday({
|
||||
field: $datePicker.get(0),
|
||||
theme: 'gitlab-theme animate-picker',
|
||||
|
@ -177,7 +179,8 @@ class DueDateSelectors {
|
|||
$datePicker.val(dateFormat(new Date(dateText), 'yyyy-mm-dd'));
|
||||
}
|
||||
});
|
||||
calendar.setDate(new Date($datePicker.val()));
|
||||
|
||||
calendar.setDate(dateFix);
|
||||
|
||||
$datePicker.data('pikaday', calendar);
|
||||
});
|
||||
|
|
|
@ -5,12 +5,15 @@ export default class GroupName {
|
|||
constructor() {
|
||||
this.titleContainer = document.querySelector('.js-title-container');
|
||||
this.title = this.titleContainer.querySelector('.title');
|
||||
this.titleWidth = this.title.offsetWidth;
|
||||
this.groupTitle = this.titleContainer.querySelector('.group-title');
|
||||
this.groups = this.titleContainer.querySelectorAll('.group-path');
|
||||
this.toggle = null;
|
||||
this.isHidden = false;
|
||||
this.init();
|
||||
|
||||
if (this.title) {
|
||||
this.titleWidth = this.title.offsetWidth;
|
||||
this.groupTitle = this.titleContainer.querySelector('.group-title');
|
||||
this.groups = this.titleContainer.querySelectorAll('.group-path');
|
||||
this.toggle = null;
|
||||
this.isHidden = false;
|
||||
this.init();
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, no-unused-vars, one-var, one-var-declaration-per-line, vars-on-top, max-len */
|
||||
import _ from 'underscore';
|
||||
import Cookies from 'js-cookie';
|
||||
import NewNavSidebar from './new_sidebar';
|
||||
|
||||
(function() {
|
||||
var hideEndFade;
|
||||
|
@ -53,6 +55,11 @@ import _ from 'underscore';
|
|||
}
|
||||
|
||||
$(() => {
|
||||
if (Cookies.get('new_nav') === 'true') {
|
||||
const newNavSidebar = new NewNavSidebar();
|
||||
newNavSidebar.bindEvents();
|
||||
}
|
||||
|
||||
$(window).on('scroll', _.throttle(applyScrollNavClass, 100));
|
||||
});
|
||||
}).call(window);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
const DateFix = {
|
||||
dashedFix(val) {
|
||||
const [y, m, d] = val.split('-');
|
||||
return new Date(y, m - 1, d);
|
||||
},
|
||||
};
|
||||
|
||||
export default DateFix;
|
|
@ -0,0 +1,23 @@
|
|||
export default class NewNavSidebar {
|
||||
constructor() {
|
||||
this.initDomElements();
|
||||
}
|
||||
|
||||
initDomElements() {
|
||||
this.$sidebar = $('.nav-sidebar');
|
||||
this.$overlay = $('.mobile-overlay');
|
||||
this.$openSidebar = $('.toggle-mobile-nav');
|
||||
this.$closeSidebar = $('.close-nav-button');
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.$openSidebar.on('click', () => this.toggleSidebarNav(true));
|
||||
this.$closeSidebar.on('click', () => this.toggleSidebarNav(false));
|
||||
this.$overlay.on('click', () => this.toggleSidebarNav(false));
|
||||
}
|
||||
|
||||
toggleSidebarNav(show) {
|
||||
this.$sidebar.toggleClass('nav-sidebar-expanded', show);
|
||||
this.$overlay.toggleClass('mobile-nav-open', show);
|
||||
}
|
||||
}
|
|
@ -104,6 +104,14 @@ import Api from './api';
|
|||
dropdownCssClass: "ajax-project-dropdown"
|
||||
});
|
||||
});
|
||||
|
||||
$('.new-project-item-select-button').on('click', function() {
|
||||
$('.project-item-select', this.parentNode).select2('open');
|
||||
});
|
||||
|
||||
$('.project-item-select').on('click', function() {
|
||||
window.location = `${$(this).val()}/${this.dataset.relativePath}`;
|
||||
});
|
||||
}
|
||||
|
||||
return ProjectSelect;
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
}
|
||||
|
||||
&:not([href]):hover {
|
||||
border-color: rgba($avatar-border, .2);
|
||||
border-color: darken($avatar-border, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@
|
|||
.avatar-counter {
|
||||
background-color: $gray-darkest;
|
||||
color: $white-light;
|
||||
border: 1px solid $border-color;
|
||||
border: 1px solid $avatar-border;
|
||||
border-radius: 1em;
|
||||
font-family: $regular_font;
|
||||
font-size: 9px;
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
|
||||
@media (max-width: $screen-sm-min) {
|
||||
width: 100%;
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
&.dropdown-open-left {
|
||||
|
@ -288,12 +289,6 @@
|
|||
padding: 5px 8px;
|
||||
color: $gl-text-color-secondary;
|
||||
}
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.droplab-dropdown {
|
||||
|
@ -466,10 +461,6 @@
|
|||
left: auto;
|
||||
right: 0;
|
||||
margin-top: -5px;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-selectable {
|
||||
|
|
|
@ -236,6 +236,8 @@ ul.content-list {
|
|||
ul.controls {
|
||||
float: right;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.btn {
|
||||
padding: 10px 14px;
|
||||
|
@ -259,6 +261,12 @@ ul.controls {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.issuable-pipeline-broken a,
|
||||
.issuable-pipeline-status a,
|
||||
.author_link {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
ul.indent-list {
|
||||
|
|
|
@ -325,7 +325,7 @@
|
|||
position: absolute;
|
||||
top: 7px;
|
||||
right: 15px;
|
||||
z-index: 2;
|
||||
z-index: 300;
|
||||
|
||||
li.active {
|
||||
font-weight: bold;
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
color: $gl-text-color;
|
||||
word-wrap: break-word;
|
||||
|
||||
[dir="auto"] {
|
||||
text-align: initial;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $md-link-color;
|
||||
}
|
||||
|
@ -112,9 +116,12 @@
|
|||
|
||||
blockquote p {
|
||||
color: $gl-grayish-blue !important;
|
||||
margin: 0;
|
||||
font-size: inherit;
|
||||
line-height: 1.5;
|
||||
|
||||
&:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
|
|
|
@ -379,7 +379,7 @@ $issue-boards-card-shadow: rgba(186, 186, 186, 0.5);
|
|||
* Avatar
|
||||
*/
|
||||
$avatar_radius: 50%;
|
||||
$avatar-border: rgba(0, 0, 0, .1);
|
||||
$avatar-border: $border-color;
|
||||
$gl-avatar-size: 40px;
|
||||
|
||||
/*
|
||||
|
|
|
@ -275,8 +275,6 @@ header.navbar-gitlab-new {
|
|||
.breadcrumbs {
|
||||
display: flex;
|
||||
min-height: 60px;
|
||||
padding-top: $gl-padding-top;
|
||||
padding-bottom: $gl-padding-top;
|
||||
color: $gl-text-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
|
@ -300,6 +298,7 @@ header.navbar-gitlab-new {
|
|||
display: flex;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
|
||||
.dropdown-menu-projects {
|
||||
margin-top: -$gl-padding;
|
||||
|
@ -330,7 +329,7 @@ header.navbar-gitlab-new {
|
|||
white-space: nowrap;
|
||||
|
||||
> a {
|
||||
&:last-of-type {
|
||||
&:last-of-type:not(:first-child) {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
@ -384,6 +383,7 @@ header.navbar-gitlab-new {
|
|||
&::after {
|
||||
content: "/";
|
||||
margin: 0 2px 0 5px;
|
||||
color: rgba($black, .65);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,3 +396,13 @@ header.navbar-gitlab-new {
|
|||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.top-area {
|
||||
.nav-controls-new-nav {
|
||||
.dropdown {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,46 +26,79 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
|
||||
.context-header {
|
||||
border-bottom: 1px solid $border-color;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px 10px 10px;
|
||||
color: $gl-text-color;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
border-bottom: 1px solid $border-color;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px 10px 10px;
|
||||
color: $gl-text-color;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $hover-background;
|
||||
color: $hover-color;
|
||||
border-color: $hover-background;
|
||||
|
||||
.avatar-container {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.settings-avatar {
|
||||
background-color: $indigo-500;
|
||||
|
||||
i {
|
||||
color: $hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
flex: 0 0 40px;
|
||||
background-color: $white-light;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $hover-background;
|
||||
color: $hover-color;
|
||||
border-color: $hover-background;
|
||||
|
||||
.avatar-container {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.settings-avatar {
|
||||
background-color: $indigo-500;
|
||||
|
||||
i {
|
||||
color: $hover-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-title,
|
||||
.group-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
|
||||
&:hover {
|
||||
.close-nav-button {
|
||||
color: $white-light;
|
||||
}
|
||||
}
|
||||
|
||||
.close-nav-button {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
padding: 0 10px;
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-avatar {
|
||||
background-color: $white-light;
|
||||
transition: background-color 100ms linear;
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
|
@ -73,7 +106,6 @@ $new-sidebar-width: 220px;
|
|||
color: $gl-text-color-secondary;
|
||||
text-align: center;
|
||||
align-self: center;
|
||||
transition: color 100ms linear;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +113,7 @@ $new-sidebar-width: 220px;
|
|||
position: fixed;
|
||||
z-index: 400;
|
||||
width: $new-sidebar-width;
|
||||
transition: width $sidebar-transition-duration;
|
||||
transition: left $sidebar-transition-duration;
|
||||
top: 50px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
@ -89,7 +121,12 @@ $new-sidebar-width: 220px;
|
|||
background-color: $gray-normal;
|
||||
box-shadow: inset -2px 0 0 $border-color;
|
||||
|
||||
&.nav-sidebar-expanded {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
transition: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
@ -118,7 +155,7 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
width: 0;
|
||||
left: (-$new-sidebar-width);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +214,6 @@ $new-sidebar-width: 220px;
|
|||
color: $hover-color;
|
||||
|
||||
.badge {
|
||||
transition: background-color 100ms linear, color 100ms linear;
|
||||
background-color: $indigo-500;
|
||||
color: $hover-color;
|
||||
}
|
||||
|
@ -185,6 +221,38 @@ $new-sidebar-width: 220px;
|
|||
}
|
||||
}
|
||||
|
||||
.toggle-mobile-nav {
|
||||
display: none;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
padding: 6px 16px;
|
||||
margin: 0 16px 0 -15px;
|
||||
height: 46px;
|
||||
border-right: 1px solid $gl-text-color-quaternary;
|
||||
|
||||
i {
|
||||
font-size: 20px;
|
||||
color: $gl-text-color-secondary;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-xs-max) {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-overlay {
|
||||
display: none;
|
||||
|
||||
&.mobile-nav-open {
|
||||
display: block;
|
||||
position: fixed;
|
||||
background-color: $black-transparent;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 300;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Make issue boards full-height now that sub-nav is gone
|
||||
|
||||
|
|
|
@ -346,13 +346,9 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.avatar:hover,
|
||||
.avatar-counter:hover {
|
||||
border-color: $issuable-sidebar-color;
|
||||
}
|
||||
|
||||
.avatar-counter:hover {
|
||||
color: $issuable-sidebar-color;
|
||||
border-color: $issuable-sidebar-color;
|
||||
}
|
||||
|
||||
.btn-clipboard {
|
||||
|
|
|
@ -376,3 +376,18 @@ table.u2f-registrations {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-wip {
|
||||
border: 1px solid $blue-500;
|
||||
background: $blue-25;
|
||||
padding: $gl-padding;
|
||||
margin-bottom: $gl-padding;
|
||||
|
||||
a {
|
||||
color: $blue-500;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,10 @@ module IssuableCollections
|
|||
|
||||
def filter_params
|
||||
set_sort_order_from_cookie
|
||||
set_default_scope
|
||||
set_default_state
|
||||
|
||||
@filter_params = params.dup
|
||||
# Skip irrelevant Rails routing params
|
||||
@filter_params = params.dup.except(:controller, :action, :namespace_id)
|
||||
@filter_params[:sort] ||= default_sort_order
|
||||
|
||||
@sort = @filter_params[:sort]
|
||||
|
@ -55,10 +55,6 @@ module IssuableCollections
|
|||
@filter_params
|
||||
end
|
||||
|
||||
def set_default_scope
|
||||
params[:scope] = 'all' if params[:scope].blank?
|
||||
end
|
||||
|
||||
def set_default_state
|
||||
params[:state] = 'opened' if params[:state].blank?
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
class Dashboard::TodosController < Dashboard::ApplicationController
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
before_action :authorize_read_project!, only: :index
|
||||
before_action :find_todos, only: [:index, :destroy_all]
|
||||
|
||||
def index
|
||||
|
@ -49,6 +50,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def authorize_read_project!
|
||||
project_id = params[:project_id]
|
||||
|
||||
if project_id.present?
|
||||
project = Project.find(project_id)
|
||||
render_404 unless can?(current_user, :read_project, project)
|
||||
end
|
||||
end
|
||||
|
||||
def find_todos
|
||||
@todos ||= TodosFinder.new(current_user, params).execute
|
||||
end
|
||||
|
|
|
@ -266,7 +266,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
if action_name == 'new'
|
||||
redirect_to external.new_issue_path
|
||||
else
|
||||
redirect_to external.project_path
|
||||
redirect_to external.issue_tracker_path
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class IssuableFinder
|
|||
include CreatedAtFilter
|
||||
|
||||
NONE = '0'.freeze
|
||||
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page].freeze
|
||||
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page state].freeze
|
||||
|
||||
attr_accessor :current_user, :params
|
||||
|
||||
|
@ -89,8 +89,14 @@ class IssuableFinder
|
|||
execute.find_by!(*params)
|
||||
end
|
||||
|
||||
def state_counter_cache_key(state)
|
||||
Digest::SHA1.hexdigest(state_counter_cache_key_components(state).flatten.join('-'))
|
||||
def state_counter_cache_key
|
||||
cache_key(state_counter_cache_key_components)
|
||||
end
|
||||
|
||||
def clear_caches!
|
||||
state_counter_cache_key_components_permutations.each do |components|
|
||||
Rails.cache.delete(cache_key(components))
|
||||
end
|
||||
end
|
||||
|
||||
def group
|
||||
|
@ -417,12 +423,19 @@ class IssuableFinder
|
|||
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
|
||||
end
|
||||
|
||||
def state_counter_cache_key_components(state)
|
||||
def state_counter_cache_key_components
|
||||
opts = params.with_indifferent_access
|
||||
opts[:state] = state
|
||||
opts.except!(*IRRELEVANT_PARAMS_FOR_CACHE_KEY)
|
||||
opts.delete_if { |_, value| value.blank? }
|
||||
|
||||
['issuables_count', klass.to_ability_name, opts.sort]
|
||||
end
|
||||
|
||||
def state_counter_cache_key_components_permutations
|
||||
[state_counter_cache_key_components]
|
||||
end
|
||||
|
||||
def cache_key(components)
|
||||
Digest::SHA1.hexdigest(components.flatten.join('-'))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,7 +75,7 @@ class IssuesFinder < IssuableFinder
|
|||
current_user.blank? || for_counting || params[:for_counting]
|
||||
end
|
||||
|
||||
def state_counter_cache_key_components(state)
|
||||
def state_counter_cache_key_components
|
||||
extra_components = [
|
||||
user_can_see_all_confidential_issues?,
|
||||
user_cannot_see_confidential_issues?(for_counting: true)
|
||||
|
@ -84,6 +84,16 @@ class IssuesFinder < IssuableFinder
|
|||
super + extra_components
|
||||
end
|
||||
|
||||
def state_counter_cache_key_components_permutations
|
||||
# Ignore the last two, as we'll provide both options for them.
|
||||
components = super.first[0..-3]
|
||||
|
||||
[
|
||||
components + [false, true],
|
||||
components + [true, false]
|
||||
]
|
||||
end
|
||||
|
||||
def by_assignee(items)
|
||||
if assignee
|
||||
items.assigned_to(assignee)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
module BreadcrumbsHelper
|
||||
def add_to_breadcrumbs(text, link)
|
||||
@breadcrumbs_extra_links ||= []
|
||||
@breadcrumbs_extra_links.push({
|
||||
text: text,
|
||||
link: link
|
||||
})
|
||||
end
|
||||
|
||||
def breadcrumb_title_link
|
||||
return @breadcrumb_link if @breadcrumb_link
|
||||
|
||||
if controller.available_action?(:index)
|
||||
url_for(action: "index")
|
||||
else
|
||||
request.path
|
||||
end
|
||||
end
|
||||
|
||||
def breadcrumb_title(title)
|
||||
return if defined?(@breadcrumb_title)
|
||||
|
||||
@breadcrumb_title = title
|
||||
end
|
||||
end
|
|
@ -235,7 +235,7 @@ module IssuablesHelper
|
|||
|
||||
def issuables_count_for_state(issuable_type, state, finder: nil)
|
||||
finder ||= public_send("#{issuable_type}_finder")
|
||||
cache_key = finder.state_counter_cache_key(state)
|
||||
cache_key = finder.state_counter_cache_key
|
||||
|
||||
@counts ||= {}
|
||||
@counts[cache_key] ||= Rails.cache.fetch(cache_key, expires_in: 2.minutes) do
|
||||
|
|
|
@ -4,6 +4,10 @@ module PageLayoutHelper
|
|||
|
||||
@page_title.push(*titles.compact) if titles.any?
|
||||
|
||||
if show_new_nav? && titles.any? && !defined?(@breadcrumb_title)
|
||||
@breadcrumb_title = @page_title.last
|
||||
end
|
||||
|
||||
# Segments are seperated by middot
|
||||
@page_title.join(" \u00b7 ")
|
||||
end
|
||||
|
|
|
@ -195,7 +195,7 @@ module ProjectsHelper
|
|||
controller.controller_name,
|
||||
controller.action_name,
|
||||
current_application_settings.cache_key,
|
||||
'v2.4'
|
||||
'v2.5'
|
||||
]
|
||||
|
||||
key << pipeline_status_cache_key(project.pipeline_status) if project.pipeline_status.has_status?
|
||||
|
|
|
@ -96,6 +96,14 @@ module Ci
|
|||
BuildSuccessWorker.perform_async(id)
|
||||
end
|
||||
end
|
||||
|
||||
before_transition any => [:failed] do |build|
|
||||
next if build.retries_max.zero?
|
||||
|
||||
if build.retries_count < build.retries_max
|
||||
Ci::Build.retry(build, build.user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def detailed_status(current_user)
|
||||
|
@ -130,6 +138,14 @@ module Ci
|
|||
success? || failed? || canceled?
|
||||
end
|
||||
|
||||
def retries_count
|
||||
pipeline.builds.retried.where(name: self.name).count
|
||||
end
|
||||
|
||||
def retries_max
|
||||
self.options.fetch(:retry, 0).to_i
|
||||
end
|
||||
|
||||
def latest?
|
||||
!retried?
|
||||
end
|
||||
|
|
|
@ -4,4 +4,8 @@ module Editable
|
|||
def is_edited?
|
||||
last_edited_at.present? && last_edited_at != created_at
|
||||
end
|
||||
|
||||
def last_edited_by
|
||||
super || User.ghost
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ class GitlabIssueTrackerService < IssueTrackerService
|
|||
project_issue_url(project, id: iid)
|
||||
end
|
||||
|
||||
def project_path
|
||||
def issue_tracker_path
|
||||
project_issues_path(project)
|
||||
end
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ class IssueTrackerService < Service
|
|||
self.issues_url.gsub(':id', iid.to_s)
|
||||
end
|
||||
|
||||
def project_path
|
||||
read_attribute(:project_url)
|
||||
def issue_tracker_path
|
||||
project_url
|
||||
end
|
||||
|
||||
def new_issue_path
|
||||
|
|
|
@ -58,22 +58,22 @@ class KubernetesService < DeploymentService
|
|||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text',
|
||||
name: 'namespace',
|
||||
title: 'Kubernetes namespace',
|
||||
placeholder: namespace_placeholder },
|
||||
{ type: 'text',
|
||||
name: 'api_url',
|
||||
title: 'API URL',
|
||||
placeholder: 'Kubernetes API URL, like https://kube.example.com/' },
|
||||
{ type: 'text',
|
||||
name: 'token',
|
||||
title: 'Service token',
|
||||
placeholder: 'Service token' },
|
||||
{ type: 'textarea',
|
||||
name: 'ca_pem',
|
||||
title: 'Custom CA bundle',
|
||||
placeholder: 'Certificate Authority bundle (PEM format)' }
|
||||
title: 'CA Certificate',
|
||||
placeholder: 'Certificate Authority bundle (PEM format)' },
|
||||
{ type: 'text',
|
||||
name: 'namespace',
|
||||
title: 'Project namespace (optional/unique)',
|
||||
placeholder: namespace_placeholder },
|
||||
{ type: 'text',
|
||||
name: 'token',
|
||||
title: 'Token',
|
||||
placeholder: 'Service token' }
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -385,9 +385,11 @@ class User < ActiveRecord::Base
|
|||
# Return (create if necessary) the ghost user. The ghost user
|
||||
# owns records previously belonging to deleted users.
|
||||
def ghost
|
||||
unique_internal(where(ghost: true), 'ghost', 'ghost%s@example.com') do |u|
|
||||
email = 'ghost%s@example.com'
|
||||
unique_internal(where(ghost: true), 'ghost', email) do |u|
|
||||
u.bio = 'This is a "Ghost User", created to hold all issues authored by users that have since been deleted. This user cannot be removed.'
|
||||
u.name = 'Ghost User'
|
||||
u.notification_email = email
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,17 +33,12 @@ module Boards
|
|||
end
|
||||
|
||||
def filter_params
|
||||
set_default_scope
|
||||
set_project
|
||||
set_state
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def set_default_scope
|
||||
params[:scope] = 'all'
|
||||
end
|
||||
|
||||
def set_project
|
||||
params[:project_id] = project.id
|
||||
end
|
||||
|
|
|
@ -174,7 +174,7 @@ module Ci
|
|||
end
|
||||
|
||||
def pipeline_created_counter
|
||||
@pipeline_created_counter ||= Gitlab::Metrics.counter(:pipelines_created_count, "Pipelines created count")
|
||||
@pipeline_created_counter ||= Gitlab::Metrics.counter(:pipelines_created_total, "Counter of pipelines created")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -183,7 +183,7 @@ class IssuableBaseService < BaseService
|
|||
after_create(issuable)
|
||||
issuable.create_cross_references!(current_user)
|
||||
execute_hooks(issuable)
|
||||
invalidate_cache_counts(issuable.assignees, issuable)
|
||||
invalidate_cache_counts(issuable, users: issuable.assignees)
|
||||
end
|
||||
|
||||
issuable
|
||||
|
@ -240,12 +240,12 @@ class IssuableBaseService < BaseService
|
|||
old_assignees: old_assignees
|
||||
)
|
||||
|
||||
if old_assignees != issuable.assignees
|
||||
new_assignees = issuable.assignees.to_a
|
||||
affected_assignees = (old_assignees + new_assignees) - (old_assignees & new_assignees)
|
||||
invalidate_cache_counts(affected_assignees.compact, issuable)
|
||||
end
|
||||
new_assignees = issuable.assignees.to_a
|
||||
affected_assignees = (old_assignees + new_assignees) - (old_assignees & new_assignees)
|
||||
|
||||
# Don't clear the project cache, because it will be handled by the
|
||||
# appropriate service (close / reopen / merge / etc.).
|
||||
invalidate_cache_counts(issuable, users: affected_assignees.compact, skip_project_cache: true)
|
||||
after_update(issuable)
|
||||
issuable.create_new_cross_references!(current_user)
|
||||
execute_hooks(issuable, 'update')
|
||||
|
@ -339,9 +339,18 @@ class IssuableBaseService < BaseService
|
|||
create_labels_note(issuable, old_labels) if issuable.labels != old_labels
|
||||
end
|
||||
|
||||
def invalidate_cache_counts(users, issuable)
|
||||
def invalidate_cache_counts(issuable, users: [], skip_project_cache: false)
|
||||
users.each do |user|
|
||||
user.public_send("invalidate_#{issuable.model_name.singular}_cache_counts")
|
||||
end
|
||||
|
||||
unless skip_project_cache
|
||||
case issuable
|
||||
when Issue
|
||||
IssuesFinder.new(nil, project_id: issuable.project_id).clear_caches!
|
||||
when MergeRequest
|
||||
MergeRequestsFinder.new(nil, project_id: issuable.target_project_id).clear_caches!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,7 +28,7 @@ module Issues
|
|||
notification_service.close_issue(issue, current_user) if notifications
|
||||
todo_service.close_issue(issue, current_user)
|
||||
execute_hooks(issue, 'close')
|
||||
invalidate_cache_counts(issue.assignees, issue)
|
||||
invalidate_cache_counts(issue, users: issue.assignees)
|
||||
end
|
||||
|
||||
issue
|
||||
|
|
|
@ -8,7 +8,7 @@ module Issues
|
|||
create_note(issue)
|
||||
notification_service.reopen_issue(issue, current_user)
|
||||
execute_hooks(issue, 'reopen')
|
||||
invalidate_cache_counts(issue.assignees, issue)
|
||||
invalidate_cache_counts(issue, users: issue.assignees)
|
||||
end
|
||||
|
||||
issue
|
||||
|
|
|
@ -13,7 +13,7 @@ module MergeRequests
|
|||
notification_service.close_mr(merge_request, current_user)
|
||||
todo_service.close_merge_request(merge_request, current_user)
|
||||
execute_hooks(merge_request, 'close')
|
||||
invalidate_cache_counts(merge_request.assignees, merge_request)
|
||||
invalidate_cache_counts(merge_request, users: merge_request.assignees)
|
||||
end
|
||||
|
||||
merge_request
|
||||
|
|
|
@ -13,7 +13,7 @@ module MergeRequests
|
|||
create_note(merge_request)
|
||||
notification_service.merge_mr(merge_request, current_user)
|
||||
execute_hooks(merge_request, 'merge')
|
||||
invalidate_cache_counts(merge_request.assignees, merge_request)
|
||||
invalidate_cache_counts(merge_request, users: merge_request.assignees)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -10,7 +10,7 @@ module MergeRequests
|
|||
execute_hooks(merge_request, 'reopen')
|
||||
merge_request.reload_diff(current_user)
|
||||
merge_request.mark_as_unchecked
|
||||
invalidate_cache_counts(merge_request.assignees, merge_request)
|
||||
invalidate_cache_counts(merge_request, users: merge_request.assignees)
|
||||
end
|
||||
|
||||
merge_request
|
||||
|
|
|
@ -31,6 +31,6 @@ class MetricsService
|
|||
end
|
||||
|
||||
def multiprocess_metrics_path
|
||||
@multiprocess_metrics_path ||= Rails.root.join(ENV['prometheus_multiproc_dir']).freeze
|
||||
::Prometheus::Client.configuration.multiprocess_files_dir
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,10 +50,12 @@ module Users
|
|||
|
||||
def migrate_issues
|
||||
user.issues.update_all(author_id: ghost_user.id)
|
||||
Issue.where(last_edited_by_id: user.id).update_all(last_edited_by_id: ghost_user.id)
|
||||
end
|
||||
|
||||
def migrate_merge_requests
|
||||
user.merge_requests.update_all(author_id: ghost_user.id)
|
||||
MergeRequest.where(merge_user_id: user.id).update_all(merge_user_id: ghost_user.id)
|
||||
end
|
||||
|
||||
def migrate_notes
|
||||
|
|
|
@ -16,7 +16,7 @@ class GitlabUploader < CarrierWave::Uploader::Base
|
|||
def self.base_dir
|
||||
return root_dir unless file_storage?
|
||||
|
||||
File.join(root_dir, 'system')
|
||||
File.join(root_dir, '-', 'system')
|
||||
end
|
||||
|
||||
def self.file_storage?
|
||||
|
|
|
@ -3,6 +3,10 @@ class PersonalFileUploader < FileUploader
|
|||
File.join(CarrierWave.root, model_path(model))
|
||||
end
|
||||
|
||||
def self.base_dir
|
||||
File.join(root_dir, 'system')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def secure_url
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
- page_title "Edit", @application.name, "Applications"
|
||||
|
||||
%h3.page-title Edit application
|
||||
- @url = admin_application_path(@application)
|
||||
= render 'form', application: @application
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
- breadcrumb_title "Applications"
|
||||
- page_title "New Application"
|
||||
|
||||
%h3.page-title New application
|
||||
- @url = admin_applications_path
|
||||
= render 'form', application: @application
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Messages"
|
||||
- page_title "Broadcast Messages"
|
||||
|
||||
= render 'form'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Messages"
|
||||
- page_title "Broadcast Messages"
|
||||
|
||||
%h3.page-title
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
- if show_new_nav? && current_user.can_create_group?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to "New group", new_group_path, class: "btn btn-new"
|
||||
|
||||
.top-area
|
||||
%ul.nav-links
|
||||
= nav_link(page: dashboard_groups_path) do
|
||||
|
@ -6,9 +10,8 @@
|
|||
= nav_link(page: explore_groups_path) do
|
||||
= link_to explore_groups_path, title: 'Explore public groups' do
|
||||
Explore public groups
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) }
|
||||
= render 'shared/groups/search_form'
|
||||
= render 'shared/groups/dropdown'
|
||||
- if current_user.can_create_group?
|
||||
= link_to new_group_path, class: "btn btn-new" do
|
||||
New group
|
||||
= link_to "New group", new_group_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}"
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
= content_for :flash_message do
|
||||
= render 'shared/project_limit'
|
||||
|
||||
- if show_new_nav? && current_user.can_create_project?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to "New project", new_project_path, class: 'btn btn-new'
|
||||
|
||||
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
|
||||
.fade-left= icon('angle-left')
|
||||
.fade-right= icon('angle-right')
|
||||
|
@ -14,9 +19,8 @@
|
|||
= link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
|
||||
Explore projects
|
||||
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) }
|
||||
= render 'shared/projects/search_form'
|
||||
= render 'shared/projects/dropdown'
|
||||
- if current_user.can_create_project?
|
||||
= link_to new_project_path, class: 'btn btn-new' do
|
||||
New project
|
||||
= link_to "New project", new_project_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}"
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
- if show_new_nav? && current_user
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet"
|
||||
|
||||
.top-area
|
||||
%ul.nav-links
|
||||
= nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
|
||||
|
@ -8,6 +12,5 @@
|
|||
Explore Snippets
|
||||
|
||||
- if current_user
|
||||
.nav-controls.hidden-xs
|
||||
= link_to new_snippet_path, class: "btn btn-new", title: "New snippet" do
|
||||
New snippet
|
||||
.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"
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Issues"
|
||||
- header_title "Issues", issues_dashboard_path(assignee_id: current_user.id)
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues")
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
|
||||
= icon('rss')
|
||||
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
|
||||
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :issues
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
|
||||
= icon('rss')
|
||||
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Merge Requests"
|
||||
- header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
|
||||
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :merge_requests
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
|
||||
|
||||
= render 'shared/issuable/filter', type: :merge_requests
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
- page_title 'Milestones'
|
||||
- header_title 'Milestones', dashboard_milestones_path
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :breadcrumbs_extra do
|
||||
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
|
||||
|
||||
.top-area
|
||||
= render 'shared/milestones_filter', counts: @milestone_states
|
||||
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
|
||||
|
||||
.milestones
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
- @no_container = true
|
||||
- @hide_top_links = true
|
||||
- @breadcrumb_title = "Projects"
|
||||
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
- @hide_top_links = true
|
||||
- @no_container = true
|
||||
|
||||
- breadcrumb_title "Projects"
|
||||
- page_title "Starred Projects"
|
||||
- header_title "Projects", dashboard_projects_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Todos"
|
||||
- header_title "Todos", dashboard_todos_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Groups"
|
||||
- header_title "Groups", dashboard_groups_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Projects"
|
||||
- header_title "Projects", dashboard_projects_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Projects"
|
||||
- header_title "Projects", dashboard_projects_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Projects"
|
||||
- header_title "Projects", dashboard_projects_path
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- @hide_top_links = true
|
||||
- page_title "Snippets"
|
||||
- header_title "Snippets", snippets_path
|
||||
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
- page_title "Issues"
|
||||
- group_issues_exists = group_issues(@group).exists?
|
||||
= render "head_issues"
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@group.name} issues")
|
||||
|
||||
- if group_issues(@group).exists?
|
||||
- if show_new_nav? && group_issues_exists
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
|
||||
= icon('rss')
|
||||
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
|
||||
|
||||
- if group_issues_exists
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :issues
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= link_to params.merge(rss_url_options), class: 'btn' do
|
||||
= icon('rss')
|
||||
%span.icon-label
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
- page_title 'Labels'
|
||||
- if show_new_nav? && can?(current_user, :admin_label, @group)
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to "New label", new_group_label_path(@group), class: "btn btn-new"
|
||||
|
||||
= render "groups/head_issues"
|
||||
|
||||
|
||||
.top-area.adjust
|
||||
.nav-text
|
||||
Labels can be applied to issues and merge requests. Group labels are available for any project within the group.
|
||||
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
- if can?(current_user, :admin_label, @group)
|
||||
= link_to new_group_label_path(@group), class: "btn btn-new" do
|
||||
New label
|
||||
= link_to "New label", new_group_label_path(@group), class: "btn btn-new"
|
||||
|
||||
.labels
|
||||
.other-labels
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Labels"
|
||||
- page_title 'New Label'
|
||||
- header_title group_title(@group, 'Labels', group_labels_path(@group))
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
- page_title "Merge Requests"
|
||||
|
||||
- if show_new_nav? && current_user
|
||||
- content_for :breadcrumbs_extra do
|
||||
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
|
||||
|
||||
- if @group_merge_requests.empty?
|
||||
= render 'shared/empty_states/merge_requests', project_select_button: true
|
||||
- else
|
||||
.top-area
|
||||
= render 'shared/issuable/nav', type: :merge_requests
|
||||
- if current_user
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
|
||||
|
||||
= render 'shared/issuable/filter', type: :merge_requests
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
- page_title "Milestones"
|
||||
- if show_new_nav? && can?(current_user, :admin_milestones, @group)
|
||||
- content_for :breadcrumbs_extra do
|
||||
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
|
||||
|
||||
= render "groups/head_issues"
|
||||
|
||||
.top-area
|
||||
= render 'shared/milestones_filter', counts: @milestone_states
|
||||
|
||||
.nav-controls
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
- if can?(current_user, :admin_milestones, @group)
|
||||
= link_to new_group_milestone_path(@group), class: "btn btn-new" do
|
||||
New milestone
|
||||
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
|
||||
|
||||
.milestones
|
||||
%ul.content-list
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Milestones"
|
||||
- page_title "Milestones"
|
||||
- header_title group_title(@group, "Milestones", group_milestones_path(@group))
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
- @breadcrumb_link = dashboard_groups_path
|
||||
- breadcrumb_title "Groups"
|
||||
- @hide_top_links = true
|
||||
- page_title 'New Group'
|
||||
- header_title "Groups", dashboard_groups_path
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
- @no_container = true
|
||||
- breadcrumb_title "Group"
|
||||
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
|
||||
|
|
|
@ -10,12 +10,15 @@
|
|||
- if content_for?(:sub_nav)
|
||||
= yield :sub_nav
|
||||
.content-wrapper{ class: "#{(layout_nav_class unless show_new_nav?)}" }
|
||||
- if show_new_nav?
|
||||
.mobile-overlay
|
||||
.alert-wrapper
|
||||
= render "layouts/broadcast"
|
||||
- if show_new_nav?
|
||||
- if content_for?(:new_global_flash)
|
||||
= yield :new_global_flash
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
- unless @hide_breadcrumbs
|
||||
= render "layouts/nav/breadcrumbs"
|
||||
= render "layouts/flash"
|
||||
= yield :flash_message
|
||||
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
- breadcrumb_title = @breadcrumb_title || controller.controller_name.humanize
|
||||
- breadcrumb_link = breadcrumb_title_link
|
||||
- hide_top_links = @hide_top_links || false
|
||||
|
||||
%nav.breadcrumbs{ role: "navigation" }
|
||||
.breadcrumbs-container{ class: [container_class, @content_class] }
|
||||
- if defined?(@new_sidebar)
|
||||
= button_tag class: 'toggle-mobile-nav', type: 'button' do
|
||||
%span.sr-only Open sidebar
|
||||
= icon ('bars')
|
||||
.breadcrumbs-links.js-title-container
|
||||
- unless hide_top_links
|
||||
.title
|
||||
= link_to "GitLab", root_path
|
||||
\/
|
||||
- if content_for?(:header_title_before)
|
||||
= yield :header_title_before
|
||||
\/
|
||||
= header_title
|
||||
%h2.breadcrumbs-sub-title
|
||||
%ul.list-unstyled
|
||||
- if content_for?(:sub_title_before)
|
||||
= yield :sub_title_before
|
||||
%li= link_to breadcrumb_title, request.path
|
||||
- if @breadcrumbs_extra_links
|
||||
- @breadcrumbs_extra_links.each do |extra|
|
||||
%li= link_to extra[:text], extra[:link]
|
||||
%li= link_to @breadcrumb_title, breadcrumb_link
|
||||
- if content_for?(:breadcrumbs_extra)
|
||||
.breadcrumbs-extra.hidden-xs= yield :breadcrumbs_extra
|
||||
= yield :header_content
|
||||
|
|
|
@ -42,18 +42,18 @@
|
|||
.key
|
||||
= icon('arrow-up', 'aria-label' => 'hidden')
|
||||
I
|
||||
%span.badge.pull-right= number_with_delimiter(assigned_issuables_count(:issues))
|
||||
%span
|
||||
Issues
|
||||
.badge= number_with_delimiter(assigned_issuables_count(: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
|
||||
.badge= number_with_delimiter(assigned_issuables_count(:merge_requests))
|
||||
= nav_link(controller: 'dashboard/snippets') do
|
||||
= link_to dashboard_snippets_path, class: 'dashboard-shortcuts-snippets', title: 'Snippets' do
|
||||
.shortcut-mappings
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
.nav-sidebar
|
||||
= link_to admin_root_path, title: 'Admin Overview', class: 'context-header' do
|
||||
.avatar-container.s40.settings-avatar
|
||||
= icon('wrench')
|
||||
.project-title Admin Area
|
||||
.context-header
|
||||
= link_to admin_root_path, title: 'Admin Overview' do
|
||||
.avatar-container.s40.settings-avatar
|
||||
= icon('wrench')
|
||||
.project-title Admin Area
|
||||
= button_tag class: 'close-nav-button', type: 'button' do
|
||||
%span.sr-only Close sidebar
|
||||
= icon ('times')
|
||||
%ul.sidebar-top-level-items
|
||||
= nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts), html_options: {class: 'home'}) do
|
||||
= link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do
|
||||
|
@ -13,7 +17,7 @@
|
|||
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
|
||||
= link_to admin_root_path, title: 'Overview' do
|
||||
%span
|
||||
Overview
|
||||
Dashboard
|
||||
= nav_link(controller: [:admin, :projects]) do
|
||||
= link_to admin_projects_path, title: 'Projects' do
|
||||
%span
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
|
||||
Projects
|
||||
|
||||
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
|
||||
= nav_link(controller: ['dashboard/groups', 'explore/groups']) do
|
||||
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
|
||||
Groups
|
||||
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
.nav-sidebar
|
||||
= link_to group_path(@group), title: @group.name, class: 'context-header' do
|
||||
.avatar-container.s40.group-avatar
|
||||
= image_tag group_icon(@group), class: "avatar s40 avatar-tile"
|
||||
.group-title
|
||||
= @group.name
|
||||
.context-header
|
||||
= link_to group_path(@group), title: @group.name do
|
||||
.avatar-container.s40.group-avatar
|
||||
= image_tag group_icon(@group), class: "avatar s40 avatar-tile"
|
||||
.group-title
|
||||
= @group.name
|
||||
= button_tag class: 'close-nav-button', type: 'button' do
|
||||
%span.sr-only Close sidebar
|
||||
= icon ('times')
|
||||
%ul.sidebar-top-level-items
|
||||
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
|
||||
= link_to group_path(@group), title: 'Home' do
|
||||
= link_to group_path(@group), title: 'About group' do
|
||||
%span
|
||||
Group
|
||||
About
|
||||
|
||||
%ul.sidebar-sub-level-items
|
||||
= nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
|
||||
= link_to group_path(@group), title: 'Group Home' do
|
||||
= link_to group_path(@group), title: 'Group details' do
|
||||
%span
|
||||
Home
|
||||
Details
|
||||
|
||||
= nav_link(path: 'groups#activity') do
|
||||
= link_to activity_group_path(@group), title: 'Activity' do
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
.nav-sidebar
|
||||
= link_to profile_path, title: 'Profile Settings', class: 'context-header' do
|
||||
.avatar-container.s40.settings-avatar
|
||||
= icon('user')
|
||||
.project-title User Settings
|
||||
.context-header
|
||||
= link_to profile_path, title: 'Profile Settings' do
|
||||
.avatar-container.s40.settings-avatar
|
||||
= icon('user')
|
||||
.project-title User Settings
|
||||
= button_tag class: 'close-nav-button', type: 'button' do
|
||||
%span.sr-only Close sidebar
|
||||
= icon ('times')
|
||||
%ul.sidebar-top-level-items
|
||||
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
|
||||
= link_to profile_path, title: 'Profile Settings' do
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
.nav-sidebar
|
||||
- can_edit = can?(current_user, :admin_project, @project)
|
||||
= link_to project_path(@project), title: @project.name, class: 'context-header' do
|
||||
.avatar-container.s40.project-avatar
|
||||
= project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile')
|
||||
.project-title
|
||||
= @project.name
|
||||
.context-header
|
||||
= link_to project_path(@project), title: @project.name do
|
||||
.avatar-container.s40.project-avatar
|
||||
= project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile')
|
||||
.project-title
|
||||
= @project.name
|
||||
= button_tag class: 'close-nav-button', type: 'button' do
|
||||
%span.sr-only Close sidebar
|
||||
= icon ('times')
|
||||
%ul.sidebar-top-level-items
|
||||
= 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
|
||||
= link_to project_path(@project), title: 'About project', class: 'shortcuts-project' do
|
||||
%span
|
||||
Project
|
||||
About
|
||||
|
||||
%ul.sidebar-sub-level-items
|
||||
= nav_link(path: 'projects#show') do
|
||||
= link_to project_path(@project), title: _('Project home'), class: 'shortcuts-project' do
|
||||
%span= _('Home')
|
||||
= link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
|
||||
%span= _('Details')
|
||||
|
||||
= nav_link(path: 'projects#activity') do
|
||||
= link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
%p
|
||||
This setting allows you to turn on or off the new upcoming navigation concept.
|
||||
.col-lg-8.syntax-theme
|
||||
.nav-wip
|
||||
%p
|
||||
The new navigation is currently a work-in-progress concept and is currently only usable on wide-screens. There are a number of improvements that we are working on in order to further refine our navigation.
|
||||
%p
|
||||
%a{ href: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/32794', target: 'blank' } Learn more
|
||||
about the improvements that are coming soon!
|
||||
= label_tag do
|
||||
.preview= image_tag "old_nav.png"
|
||||
%input.js-experiment-feature-toggle{ type: "radio", value: "false", name: "new_nav", checked: !show_new_nav? }
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Profile"
|
||||
- @content_class = "limit-container-width" unless fluid_layout
|
||||
= render 'profiles/head'
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
- page_title 'Two-Factor Authentication', 'Account'
|
||||
- header_title "Two-Factor Authentication", profile_two_factor_auth_path
|
||||
- if show_new_nav?
|
||||
- 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
|
||||
|
||||
= render 'profiles/head'
|
||||
|
||||
- if inject_u2f_api?
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
- @no_container = true
|
||||
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Project", project_path(@project))
|
||||
|
||||
- page_title "Activity"
|
||||
= render "projects/head"
|
||||
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
|
||||
.tree-holder
|
||||
.nav-block
|
||||
.tree-controls
|
||||
= link_to download_project_job_artifacts_path(@project, @build),
|
||||
rel: 'nofollow', download: '', class: 'btn btn-default download' do
|
||||
= icon('download')
|
||||
Download artifacts archive
|
||||
|
||||
%ul.breadcrumb.repo-breadcrumb
|
||||
%li
|
||||
= link_to 'Artifacts', browse_project_job_artifacts_path(@project, @build)
|
||||
|
@ -18,6 +12,12 @@
|
|||
%li
|
||||
= link_to truncate(title, length: 40), browse_project_job_artifacts_path(@project, @build, path)
|
||||
|
||||
.tree-controls
|
||||
= link_to download_project_job_artifacts_path(@project, @build),
|
||||
rel: 'nofollow', download: '', class: 'btn btn-default download' do
|
||||
= icon('download')
|
||||
Download artifacts archive
|
||||
|
||||
.tree-content-holder
|
||||
%table.table.tree-table
|
||||
%thead
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Repository"
|
||||
- @no_container = true
|
||||
- page_title "Edit", @blob.path, @ref
|
||||
- content_for :page_specific_javascripts do
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Repository"
|
||||
- page_title "New File", @path.presence, @ref
|
||||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_tag('lib/ace.js')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- breadcrumb_title "Repository"
|
||||
- @no_container = true
|
||||
|
||||
- page_title @blob.path, @ref
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
- page_title "Boards"
|
||||
|
||||
- if show_new_nav?
|
||||
- content_for :sub_title_before do
|
||||
%li= link_to "Issues", project_issues_path(@project)
|
||||
- add_to_breadcrumbs("Issues", project_issues_path(@project))
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
= webpack_bundle_tag 'common_vue'
|
||||
|
|
|
@ -2,11 +2,15 @@
|
|||
- page_title "Branches"
|
||||
= render "projects/commits/head"
|
||||
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Repository", project_tree_path(@project))
|
||||
|
||||
%div{ class: container_class }
|
||||
.top-area.adjust
|
||||
.nav-text
|
||||
Protected branches can be managed in
|
||||
= link_to 'project settings', project_protected_branches_path(@project)
|
||||
- if can?(current_user, :admin_project, @project)
|
||||
.nav-text
|
||||
Protected branches can be managed in
|
||||
= link_to 'project settings', project_protected_branches_path(@project)
|
||||
|
||||
.nav-controls
|
||||
= form_tag(filter_branches_path, method: :get) do
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
- @no_container = true
|
||||
- breadcrumb_title _("Commits")
|
||||
|
||||
- page_title _("Commits"), @ref
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
|
||||
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Repository", project_tree_path(@project))
|
||||
|
||||
= content_for :sub_nav do
|
||||
= render "head"
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title "Compare"
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Repository", project_tree_path(@project))
|
||||
= render "projects/commits/head"
|
||||
|
||||
%div{ class: container_class }
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
- @no_container = true
|
||||
- breadcrumb_title "Compare"
|
||||
- page_title "#{params[:from]}...#{params[:to]}"
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Repository", project_tree_path(@project))
|
||||
= render "projects/commits/head"
|
||||
|
||||
%div{ class: container_class }
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title "Cycle Analytics"
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Project", project_path(@project))
|
||||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_bundle_tag('common_vue')
|
||||
= page_specific_javascript_bundle_tag('cycle_analytics')
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
- page_title "Environments"
|
||||
= render "projects/pipelines/head"
|
||||
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_bundle_tag('common_vue')
|
||||
= page_specific_javascript_bundle_tag("environments")
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
- @no_container = true
|
||||
- breadcrumb_title "Environments"
|
||||
- page_title 'New Environment'
|
||||
= render "projects/pipelines/head"
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title "Charts"
|
||||
- if show_new_nav?
|
||||
- add_to_breadcrumbs("Repository", project_tree_path(@project))
|
||||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_bundle_tag('common_d3')
|
||||
= page_specific_javascript_bundle_tag('graphs')
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue