Skip to content
Snippets Groups Projects
Commit 4a7dee11 authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖
Browse files

Automatic merge of gitlab-org/gitlab master

parents 77ea8f81 16ed88d1
No related branches found
No related tags found
No related merge requests found
Showing
with 69 additions and 34 deletions
b1841c6d79f62066335ad4d44efa21f3c5f77c03
ddcce8f5e7878c997a9863f5c3ed532d7126256b
......@@ -74,6 +74,7 @@ export const config = {
},
};
}
return incomingWidget || existingWidget;
});
},
......
......@@ -77,3 +77,5 @@ export const DROPDOWN_ORDER = [
];
export const FETCH_TYPES = ['generic', 'search'];
export const SEARCH_INPUT_FIELD_MAX_WIDTH = '640px';
import Vue from 'vue';
import * as Sentry from '@sentry/browser';
import Translate from '~/vue_shared/translate';
import HeaderSearchApp from './components/app.vue';
import createStore from './store';
import { SEARCH_INPUT_FIELD_MAX_WIDTH } from './constants';
Vue.use(Translate);
export const initHeaderSearchApp = (search = '') => {
const el = document.getElementById('js-header-search');
let navBarEl = null;
const headerEl = document.querySelector('.header-content');
if (!el) {
if (!el && !headerEl) {
return false;
}
const searchContainer = headerEl.querySelector('.global-search-container');
const newHeader = headerEl.querySelector('.header-search-new');
const { searchPath, issuesPath, mrPath, autocompletePath } = el.dataset;
let { searchContext } = el.dataset;
searchContext = JSON.parse(searchContext);
try {
searchContext = JSON.parse(searchContext);
newHeader.style.maxWidth = SEARCH_INPUT_FIELD_MAX_WIDTH;
} catch (error) {
Sentry.captureException(error);
}
return new Vue({
el,
store: createStore({ searchPath, issuesPath, mrPath, autocompletePath, searchContext, search }),
mounted() {
navBarEl = document.querySelector('.header-content');
},
render(createElement) {
return createElement(HeaderSearchApp, {
on: {
expandSearchBar: () => {
navBarEl?.classList.add('header-search-is-active');
searchContainer.style.flexGrow = '1';
},
collapseSearchBar: () => {
navBarEl?.classList.remove('header-search-is-active');
searchContainer.style.flexGrow = '0';
},
},
});
......
......@@ -522,15 +522,23 @@ function handleContinueList(e, textArea) {
if (!(e.key === 'Enter')) return;
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
if (textArea.selectionStart !== textArea.selectionEnd) return;
// prevent unintended line breaks inserted using Japanese IME on MacOS
if (compositioningNoteText) return;
const firstSelectedLine = linesFromSelection(textArea).lines[0];
const selectedLines = linesFromSelection(textArea);
const firstSelectedLine = selectedLines.lines[0];
const listLineMatch = firstSelectedLine.match(LIST_LINE_HEAD_PATTERN);
if (listLineMatch) {
const { leader, indent, content, isOl } = listLineMatch.groups;
const emptyListItem = !content;
const prefixLength = leader.length + indent.length;
if (selectedLines.selectionStart - selectedLines.startPos < prefixLength) {
// cursor in the indent/leader area, allow the natural line feed to be added
return;
}
if (emptyListItem) {
// erase empty list item - select the text and allow the
......
......@@ -10,7 +10,7 @@ export default function getStandardContext({ extra = {} } = {}) {
...data,
source: SNOWPLOW_JS_SOURCE,
google_analytics_id: getCookie(GOOGLE_ANALYTICS_ID_COOKIE_NAME) ?? '',
extra: extra || data.extra,
extra: { ...data.extra, ...extra },
},
};
}
......@@ -156,6 +156,7 @@ export default {
modal-id="work-item-detail-modal"
header-class="gl-p-0 gl-pb-2!"
scrollable
data-testid="work-item-detail-modal"
@hide="closeModal"
>
<gl-alert v-if="error" variant="danger" @dismiss="error = false">
......
......@@ -3,6 +3,15 @@
#import "~/work_items/graphql/milestone.fragment.graphql"
fragment WorkItemMetadataWidgets on WorkItemWidget {
... on WorkItemWidgetDescription {
type
}
... on WorkItemWidgetStartAndDueDate {
type
}
... on WorkItemWidgetNotes {
type
}
... on WorkItemWidgetMilestone {
type
milestone {
......@@ -11,6 +20,8 @@ fragment WorkItemMetadataWidgets on WorkItemWidget {
}
... on WorkItemWidgetAssignees {
type
allowsMultipleAssignees
canInviteMembers
assignees {
nodes {
...User
......
$search-input-field-min-width: 320px;
$search-input-field-max-width: 640px;
$search-input-field-x-min-width: 200px;
.navbar-gitlab {
......@@ -80,16 +79,6 @@ $search-input-field-x-min-width: 200px;
.navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
.header-search-new {
max-width: $search-input-field-max-width;
}
&.header-search-is-active {
.global-search-container {
flex-grow: 1;
}
}
}
.header-search {
......
......@@ -837,9 +837,6 @@ kbd {
.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
.navbar-gitlab .header-content .header-search-new {
max-width: 640px;
}
.navbar-gitlab .header-search {
min-width: 320px;
}
......
......@@ -837,9 +837,6 @@ kbd {
.navbar-gitlab .header-content .navbar-collapse > ul.nav > li:not(.d-none) {
margin: 0 2px;
}
.navbar-gitlab .header-content .header-search-new {
max-width: 640px;
}
.navbar-gitlab .header-search {
min-width: 320px;
}
......
......@@ -17,7 +17,7 @@ def resolve(project_path:, iid:, milestone: nil)
merge_request = authorized_find!(project_path: project_path, iid: iid)
project = merge_request.project
::MergeRequests::UpdateService.new(project: project, current_user: current_user, params: { milestone: milestone })
::MergeRequests::UpdateService.new(project: project, current_user: current_user, params: { milestone_id: milestone&.id })
.execute(merge_request)
{
......
......@@ -183,4 +183,11 @@ def cache_key
resolved_at
].join(':')
end
# Consolidate discussions GID. There is no need to have different GID for different class names as the discussion_id
# hash is already unique per discussion. This also fixes the issue where same discussion may return different GIDs
# depending on number of notes it has.
def to_global_id(options = {})
GlobalID.new(::Gitlab::GlobalId.build(model_name: Discussion.to_s, id: id))
end
end
......@@ -34,8 +34,9 @@ def can_set_issuable_metadata?(issuable)
end
def filter_params(issuable)
params.delete(:milestone)
unless can_set_issuable_metadata?(issuable)
params.delete(:milestone)
params.delete(:milestone_id)
params.delete(:labels)
params.delete(:add_label_ids)
......
......@@ -145,7 +145,7 @@ def base_params
if push_options[:milestone]
milestone = Milestone.for_projects_and_groups(@project, @project.ancestors_upto)&.find_by_name(push_options[:milestone])
params[:milestone] = milestone if milestone
params[:milestone_id] = milestone.id if milestone
end
if params.key?(:description)
......
......@@ -4,7 +4,7 @@ module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
Milestone.transaction do
update_params = { milestone: nil, skip_milestone_email: true }
update_params = { milestone_id: nil, skip_milestone_email: true }
milestone.issues.each do |issue|
Issues::UpdateService.new(project: parent, current_user: current_user, params: update_params).execute(issue)
......
......@@ -15,6 +15,7 @@
gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(
namespace: namespace,
project: @project,
user: current_user
user: current_user,
new_nav: show_super_sidebar?
).to_context.to_json.to_json}
gl.snowplowPseudonymizedPageUrl = #{masked_page_url(group: namespace, project: @project).to_json};
......@@ -774,6 +774,9 @@
Settings.cron_jobs['elastic_migration_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_migration_worker']['cron'] ||= '*/30 * * * *'
Settings.cron_jobs['elastic_migration_worker']['job_class'] ||= 'Elastic::MigrationWorker'
Settings.cron_jobs['search_index_curation_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['search_index_curation_worker']['cron'] ||= '*/30 * * * *'
Settings.cron_jobs['search_index_curation_worker']['job_class'] ||= 'Search::IndexCurationWorker'
Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} #{rand(3..4)} * * * UTC"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker'
......
......@@ -753,7 +753,7 @@ Example response:
## List merge requests associated with a commit
Get a list of merge requests related to the specified commit.
Returns information about the merge request that originally introduced a specific commit.
```plaintext
GET /projects/:id/repository/commits/:sha/merge_requests
......
......@@ -15,6 +15,15 @@ files or directories in a repository.
- You can set your merge requests so they must be approved by Code Owners before merge.
- You can protect a branch and allow only Code Owners to approve changes to the branch.
<div class="video-fallback">
Video introduction: <a href="https://www.youtube.com/watch?v=RoyBySTUSB0">Code Owners</a>.
</div>
<figure class="video-container">
<iframe src="https://www.youtube-nocookie.com/embed/RoyBySTUSB0" frameborder="0" allowfullscreen> </iframe>
</figure>
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Use Code Owners and approvers together with
[approval rules](merge_requests/approvals/rules.md) to build a flexible approval
workflow:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment