Commit 60cbf2b5 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'ce-to-ee-9-3-rc7' into '9-3-stable-ee-rc7'

Prepare 9.3 EE RC7 CE to EE

See merge request !2215
parents 8dca368c 062e86f2
Pipeline #9224778 passed with stages
in 115 minutes and 27 seconds
......@@ -491,6 +491,7 @@ class FilteredSearchManager {
}
searchState(e) {
e.preventDefault();
const target = e.currentTarget;
// remove focus outline after click
target.blur();
......
......@@ -22,6 +22,7 @@ export default class IssuableBulkUpdateSidebar {
initDomElements() {
this.$page = $('.page-with-sidebar');
this.$sidebar = $('.right-sidebar');
this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
this.$bulkEditSubmitBtn = $('.update-selected-issues');
this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
......@@ -113,6 +114,7 @@ export default class IssuableBulkUpdateSidebar {
toggleSidebarDisplay(show) {
this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
this.$sidebarInnerContainer.toggleClass(HIDDEN_CLASS, !show);
this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -7,6 +7,13 @@ import Cookies from 'js-cookie';
function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this);
this.sidebar = $('aside');
this.$sidebarInner = this.sidebar.find('.issuable-sidebar');
this.$navGitlab = $('.navbar-gitlab');
this.$layoutNav = $('.layout-nav');
this.$subScroll = $('.sub-nav-scroll');
this.$rightSidebar = $('.js-right-sidebar');
this.removeListeners();
this.addEventListeners();
}
......@@ -21,14 +28,15 @@ import Cookies from 'js-cookie';
Sidebar.prototype.addEventListeners = function() {
const $document = $(document);
const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight, 10);
const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight.bind(this), 20);
const debouncedSetSidebarHeight = _.debounce(this.setSidebarHeight.bind(this), 200);
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
$('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden);
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
$(window).on('resize', () => throttledSetSidebarHeight());
$document.on('scroll', () => throttledSetSidebarHeight());
$document.on('scroll', () => debouncedSetSidebarHeight());
$document.on('click', '.js-sidebar-toggle', function(e, triggered) {
var $allGutterToggleIcons, $this, $thisIcon;
e.preventDefault();
......@@ -207,13 +215,14 @@ import Cookies from 'js-cookie';
};
Sidebar.prototype.setSidebarHeight = function() {
const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + $('.sub-nav-scroll').outerHeight();
const $rightSidebar = $('.js-right-sidebar');
const $navHeight = this.$navGitlab.outerHeight() + this.$layoutNav.outerHeight() + (this.$subScroll ? this.$subScroll.outerHeight() : 0);
const diff = $navHeight - $(window).scrollTop();
if (diff > 0) {
$rightSidebar.outerHeight($(window).height() - diff);
this.$rightSidebar.outerHeight($(window).height() - diff);
this.$sidebarInner.height('100%');
} else {
$rightSidebar.outerHeight('100%');
this.$rightSidebar.outerHeight('100%');
this.$sidebarInner.height('');
}
};
......
function expandSectionParent($section, $content) {
$section.addClass('expanded');
$content.off('animationend.expandSectionParent');
}
function expandSection($section) {
$section.find('.js-settings-toggle').text('Close');
$section.find('.settings-content').addClass('expanded').off('scroll').scrollTop(0);
const $content = $section.find('.settings-content');
$content.addClass('expanded').off('scroll.expandSection').scrollTop(0);
if ($content.hasClass('no-animate')) {
expandSectionParent($section, $content);
} else {
$content.on('animationend.expandSectionParent', () => expandSectionParent($section, $content));
}
}
function closeSection($section) {
$section.find('.js-settings-toggle').text('Expand');
$section.find('.settings-content').removeClass('expanded').on('scroll', () => expandSection($section));
const $content = $section.find('.settings-content');
$content.removeClass('expanded').on('scroll.expandSection', () => expandSection($section));
$section.removeClass('expanded');
}
function toggleSection($section) {
......@@ -21,7 +38,7 @@ function toggleSection($section) {
export default function initSettingsPanels() {
$('.settings').each((i, elm) => {
const $section = $(elm);
$section.on('click', '.js-settings-toggle', () => toggleSection($section));
$section.find('.settings-content:not(.expanded)').on('scroll', () => expandSection($section));
$section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
$section.find('.settings-content:not(.expanded)').on('scroll.expandSection', () => expandSection($section));
});
}
......@@ -45,8 +45,7 @@
li {
display: flex;
a,
.btn-link {
a {
padding: $gl-btn-padding;
padding-bottom: 11px;
font-size: 14px;
......@@ -68,29 +67,7 @@
}
}
.btn-link {
padding-top: 16px;
padding-left: 15px;
padding-right: 15px;
border-left: none;
border-right: none;
border-top: none;
border-radius: 0;
&:hover,
&:active,
&:focus {
background-color: transparent;
}
&:active {
outline: 0;
box-shadow: none;
}
}
&.active a,
&.active .btn-link {
&.active a {
border-bottom: 2px solid $link-underline-blue;
color: $black;
font-weight: 600;
......
......@@ -97,17 +97,19 @@
.issues-bulk-update.right-sidebar {
@include maintain-sidebar-dimensions;
transition: right $sidebar-transition-duration;
right: -$gutter-width;
width: 0;
padding: 0;
transition: width $sidebar-transition-duration;
&.right-sidebar-expanded {
@include maintain-sidebar-dimensions;
right: 0;
width: $gutter-width;
}
&.right-sidebar-collapsed {
@include maintain-sidebar-dimensions;
right: -$gutter-width;
width: 0;
padding: 0;
.block {
padding: 16px 0;
......@@ -118,5 +120,6 @@
.issuable-sidebar {
padding: 0 3px;
width: calc(100% + 35px);
}
}
......@@ -44,6 +44,10 @@
&:target,
&.target {
background: $line-target-blue;
&.system-note .note-body .note-text.system-note-commit-list::after {
background: linear-gradient(rgba($line-target-blue, 0.1) -100px, $line-target-blue 100%);
}
}
.avatar {
......
......@@ -325,6 +325,7 @@ $note-disabled-comment-color: #b2b2b2;
$note-targe3-outside: #fffff0;
$note-targe3-inside: #ffffd3;
$note-line2-border: #ddd;
$note-icon-gutter-width: 55px;
/*
......
......@@ -203,7 +203,7 @@
.issuable-sidebar {
width: calc(100% + 100px);
height: 100%;
height: calc(100% - #{$header-height});
overflow-y: scroll;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
......
......@@ -148,8 +148,20 @@
padding: 6px 0;
}
.notes-form > li {
border: 0;
.notes.notes-form > li.timeline-entry {
@include notes-media('max', $screen-sm-max) {
padding: 0;
}
.timeline-content {
@include notes-media('max', $screen-sm-max) {
margin: 0;
}
}
.timeline-entry-inner {
border: 0;
}
}
.note-edit-form {
......
......@@ -14,16 +14,6 @@ ul.notes {
margin: 0;
padding: 0;
.timeline-content {
margin-left: 55px;
&.timeline-content-form {
@include notes-media('max', $screen-sm-max) {
margin-left: 0;
}
}
}
.note-created-ago,
.note-updated-at {
white-space: nowrap;
......@@ -46,17 +36,49 @@ ul.notes {
}
}
> li {
padding: $gl-padding $gl-btn-padding;
> li { // .timeline-entry
padding: 0;
display: block;
position: relative;
border-bottom: 1px solid $white-normal;
border-bottom: 0;
@include notes-media('min', $screen-sm-min) {
padding-left: $note-icon-gutter-width;
}
&:last-child {
// Override `.timeline > li:last-child { border-bottom: none; }`
.timeline-entry-inner {
padding: $gl-padding $gl-btn-padding;
border-bottom: 1px solid $white-normal;
}
&:target,
&.target {
border-bottom: 1px solid $white-normal;
&:not(:first-child) {
border-top: 1px solid $white-normal;
margin-top: -1px;
}
.timeline-entry-inner {
border-bottom: 0;
}
}
.timeline-icon {
@include notes-media('min', $screen-sm-min) {
margin-left: -$note-icon-gutter-width;
}
}
.timeline-content {
margin-left: $note-icon-gutter-width;
@include notes-media('min', $screen-sm-min) {
margin-left: 0;
}
}
&.being-posted {
pointer-events: none;
opacity: 0.5;
......@@ -73,7 +95,7 @@ ul.notes {
}
&.note-discussion {
&.timeline-entry {
.timeline-entry-inner {
padding: $gl-padding 10px;
}
}
......@@ -152,13 +174,8 @@ ul.notes {
.system-note {
font-size: 14px;
padding-left: 0;
clear: both;
@include notes-media('min', $screen-sm-min) {
margin-left: 65px;
}
.note-header-info {
padding-bottom: 0;
}
......@@ -192,13 +209,16 @@ ul.notes {
.timeline-icon {
float: left;
@include notes-media('min', $screen-sm-min) {
margin-left: 0;
width: auto;
}
svg {
width: 16px;
height: 16px;
fill: $gray-darkest;
position: absolute;
left: 0;
top: 2px;
margin-top: 2px;
}
}
......@@ -250,7 +270,7 @@ ul.notes {
&::after {
content: '';
width: 100%;
height: 67px;
height: 70px;
position: absolute;
left: 0;
bottom: 0;
......@@ -639,15 +659,12 @@ ul.notes {
.discussion-body,
.diff-file {
.notes .note {
padding-left: $gl-padding;
padding-right: $gl-padding;
&.system-note {
padding-left: 0;
border-bottom: 1px solid $white-normal;
@media (min-width: $screen-sm-min) {
margin-left: 70px;
}
.timeline-entry-inner {
padding-left: $gl-padding;
padding-right: $gl-padding;
border-bottom: none;
}
}
}
......
......@@ -29,6 +29,10 @@
&:first-of-type {
margin-top: 10px;
}
&.expanded {
overflow: visible;
}
}
.settings-header {
......
......@@ -6,7 +6,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
before_action :authorize_admin_project!
before_action :authorize_update_deploy_key!, only: [:edit, :update]
layout "project_settings"
layout 'project_settings'
def index
respond_to do |format|
......@@ -73,7 +73,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
protected
def deploy_key
@deploy_key ||= @project.deploy_keys.find(params[:id])
@deploy_key ||= DeployKey.find(params[:id])
end
def create_params
......
......@@ -16,8 +16,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
respond_to do |format|
format.html
format.json do
Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: {
environments: EnvironmentSerializer
.new(project: @project, current_user: @current_user)
......
......@@ -142,17 +142,6 @@ module Ci
ExpandVariables.expand(environment, simple_variables) if environment
end
def environment_url
return @environment_url if defined?(@environment_url)
@environment_url =
if unexpanded_url = options&.dig(:environment, :url)
ExpandVariables.expand(unexpanded_url, simple_variables)
else
persisted_environment&.external_url
end
end
def has_environment?
environment.present?
end
......@@ -196,7 +185,7 @@ module Ci
slugified.gsub(/[^a-z0-9]/, '-')[0..62]
end
# Variables whose value does not depend on other variables
# Variables whose value does not depend on environment
def simple_variables
variables = predefined_variables
variables += project.predefined_variables
......@@ -211,7 +200,8 @@ module Ci
variables
end
# All variables, including those dependent on other variables
# All variables, including those dependent on environment, which could
# contain unexpanded variables.
def variables
simple_variables.concat(persisted_environment_variables)
end
......@@ -490,9 +480,10 @@ module Ci
variables = persisted_environment.predefined_variables
if url = environment_url
variables << { key: 'CI_ENVIRONMENT_URL', value: url, public: true }
end
# Here we're passing unexpanded environment_url for runner to expand,
# and we need to make sure that CI_ENVIRONMENT_NAME and
# CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
variables << { key: 'CI_ENVIRONMENT_URL', value: environment_url, public: true } if environment_url
variables
end
......@@ -515,6 +506,10 @@ module Ci
variables
end
def environment_url
options&.dig(:environment, :url) || persisted_environment&.external_url
end
def build_attributes_from_config
return {} unless pipeline.config_processor
......
......@@ -2,7 +2,7 @@ class CreateDeploymentService
attr_reader :job
delegate :expanded_environment_name,
:environment_url,
:variables,
:project,
to: :job
......@@ -14,7 +14,8 @@ class CreateDeploymentService
return unless executable?
ActiveRecord::Base.transaction do
environment.external_url = environment_url if environment_url
environment.external_url = expanded_environment_url if
expanded_environment_url
environment.fire_state_event(action)
return unless environment.save
......@@ -49,6 +50,17 @@ class CreateDeploymentService
@environment_options ||= job.options&.dig(:environment) || {}
end
def expanded_environment_url
return @expanded_environment_url if defined?(@expanded_environment_url)
@expanded_environment_url =
ExpandVariables.expand(environment_url, variables) if environment_url
end
def environment_url
environment_options[:url]
end
def on_stop
environment_options[:on_stop]
end
......
- type = local_assigns.fetch(:type)
%aside.issues-bulk-update.js-right-sidebar.right-sidebar.affix-top{ data: { "offset-top" => "50", "spy" => "affix" }, "aria-live" => "polite" }
.issuable-sidebar
.issuable-sidebar.hidden
= form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
.block
.filter-item.inline.update-issues-btn.pull-left
......
- type = local_assigns.fetch(:type, :issues)
- page_context_word = type.to_s.humanize(capitalize: false)
- issuables = @issues || @merge_requests
- closed_title = 'Filter by issues that are currently closed.'
%ul.nav-links.issues-state-filters
%li{ class: active_when(params[:state] == 'opened') }>
%button.btn.btn-link{ id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", type: 'button', data: { state: 'opened' } }
= link_to page_filter_path(state: 'opened', label: true), id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", data: { state: 'opened' } do
#{issuables_state_counter_text(type, :opened)}
- if type == :merge_requests
%li{ class: active_when(params[:state] == 'merged') }>
%button.btn.btn-link{ id: 'state-merged', title: 'Filter by merge requests that are currently merged.', type: 'button', data: { state: 'merged' } }
= link_to page_filter_path(state: 'merged', label: true), id: 'state-merged', title: 'Filter by merge requests that are currently merged.', data: { state: 'merged' } do
#{issuables_state_counter_text(type, :merged)}
- closed_title = 'Filter by merge requests that are currently closed and unmerged.'
%li{ class: active_when(params[:state] == 'closed') }>
%button.btn.btn-link{ id: 'state-closed', title: closed_title, type: 'button', data: { state: 'closed' } }
#{issuables_state_counter_text(type, :closed)}
%li{ class: active_when(params[:state] == 'closed') }>
= link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by merge requests that are currently closed and unmerged.', data: { state: 'closed' } do
#{issuables_state_counter_text(type, :closed)}
- else
%li{ class: active_when(params[:state] == 'closed') }>
= link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by issues that are currently closed.', data: { state: 'closed' } do
#{issuables_state_counter_text(type, :closed)}
%li{ class: active_when(params[:state] == 'all') }>
%button.btn.btn-link{ id: 'state-all', title: "Show all #{page_context_word}.", type: 'button', data: { state: 'all' } }
= link_to page_filter_path(state: 'all', label: true), id: 'state-all', title: "Show all #{page_context_word}.", data: { state: 'all' } do
#{issuables_state_counter_text(type, :all)}
......@@ -6,13 +6,14 @@
- if can_create_note?
%ul.notes.notes-form.timeline
%li.timeline-entry
.flash-container.timeline-content
.timeline-entry-inner
.flash-container.timeline-content
.timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) }
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
.timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) }
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user
.disabled-comment.text-center.prepend-top-default
Please
......
---
title: Fix edit button for deploy keys available from other projects
merge_request: 12301
author: Alexander Randa
---
title: Standardize timeline note margins across different viewport sizes
merge_request: 12364
author:
---
title: Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL
merge_request: 12344
author:
---
title: Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab-ee/issues/2677
merge_request: 12347
author:
---
title: Fix GitHub importer performance on branch existence check
merge_request:
author:
......@@ -3,19 +3,11 @@ class AddStageIdToCiBuilds < ActiveRecord::Migration
DOWNTIME = false
disable_ddl_transaction!
def up
add_column :ci_builds, :stage_id, :integer
add_concurrent_foreign_key :ci_builds, :ci_stages, column: :stage_id, on_delete: :cascade
add_concurrent_index :ci_builds, :stage_id
end
def down
remove_foreign_key :ci_builds, column: :stage_id
remove_concurrent_index :ci_builds, :stage_id
remove_column :ci_builds, :stage_id, :integer
end
end
class AddIndexForHeadPipelineMergeRequest < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :merge_requests, :head_pipeline_id
end
def down
remove_concurrent_index :merge_requests, :head_pipeline_id if index_exists?(:merge_requests, :head_pipeline_id)
end
end
......@@ -7,6 +7,8 @@ class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration
DOWNTIME = false
def up
disable_statement_timeout
update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1)
end
......
class RemoveStageIdIndexFromBuilds < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
if index_exists?(:ci_builds, :stage_id)
remove_foreign_key(:ci_builds, column: :stage_id)