Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-08-11 06:08:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-11 06:08:51 +0300
commitcf127374b5f72c00426acad9f2432064eeb1f1e3 (patch)
tree710922928ab9888128a6c9f9dbc0edbf6ef2f8af /app
parent7303dddd09bf28d28e36666f0cc2775e9fa27872 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue71
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js8
-rw-r--r--app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/listbox_input/init_listbox_inputs.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/listbox_input/listbox_input.vue6
-rw-r--r--app/controllers/projects/discussions_controller.rb23
-rw-r--r--app/models/concerns/noteable.rb4
-rw-r--r--app/models/discussion.rb4
-rw-r--r--app/presenters/merge_request_presenter.rb11
-rw-r--r--app/serializers/base_discussion_entity.rb6
-rw-r--r--app/serializers/note_entity.rb4
-rw-r--r--app/serializers/project_note_entity.rb8
-rw-r--r--app/views/discussions/_diff_with_notes.html.haml2
-rw-r--r--app/views/profiles/preferences/show.html.haml11
14 files changed, 81 insertions, 82 deletions
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 4e816038539..4a6b6d5233f 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -245,15 +245,16 @@ export default {
},
methods: {
...mapActions(['toggleResolveNote']),
- shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState) {
- const newResolvedStateAfterUpdate =
- this.shouldBeResolved && this.shouldBeResolved(shouldResolve);
-
- const shouldToggleState =
- newResolvedStateAfterUpdate !== undefined &&
- beforeSubmitDiscussionState !== newResolvedStateAfterUpdate;
-
- return shouldResolve || shouldToggleState;
+ shouldToggleResolved(beforeSubmitDiscussionState) {
+ return (
+ this.showResolveDiscussionToggle && beforeSubmitDiscussionState !== this.newResolvedState()
+ );
+ },
+ newResolvedState() {
+ return (
+ (this.discussionResolved && !this.isUnresolving) ||
+ (!this.discussionResolved && this.isResolving)
+ );
},
editMyLastNote() {
if (this.updatedNoteBody === '') {
@@ -293,7 +294,7 @@ export default {
}
this.updatedNoteBody = '';
},
- handleUpdate(shouldResolve) {
+ handleUpdate() {
const beforeSubmitDiscussionState = this.discussionResolved;
this.isSubmitting = true;
@@ -309,23 +310,13 @@ export default {
() => {
this.isSubmitting = false;
- if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) {
+ if (this.shouldToggleResolved(beforeSubmitDiscussionState)) {
this.resolveHandler(beforeSubmitDiscussionState);
}
},
this.discussionResolved ? !this.isUnresolving : this.isResolving,
);
},
- shouldBeResolved(resolveStatus) {
- if (this.withBatchComments) {
- return (
- (this.discussionResolved && !this.isUnresolving) ||
- (!this.discussionResolved && this.isResolving)
- );
- }
-
- return resolveStatus;
- },
handleAddToReview() {
// check if draft should resolve thread
const shouldResolve =
@@ -390,21 +381,22 @@ export default {
/>
</comment-field-layout>
<div class="note-form-actions">
+ <p v-if="showResolveDiscussionToggle">
+ <label>
+ <template v-if="discussionResolved">
+ <gl-form-checkbox v-model="isUnresolving" class="js-unresolve-checkbox">
+ {{ __('Unresolve thread') }}
+ </gl-form-checkbox>
+ </template>
+ <template v-else>
+ <gl-form-checkbox v-model="isResolving" class="js-resolve-checkbox">
+ {{ __('Resolve thread') }}
+ </gl-form-checkbox>
+ </template>
+ </label>
+ </p>
+
<template v-if="showBatchCommentsActions">
- <p v-if="showResolveDiscussionToggle">
- <label>
- <template v-if="discussionResolved">
- <gl-form-checkbox v-model="isUnresolving" class="js-unresolve-checkbox">
- {{ __('Unresolve thread') }}
- </gl-form-checkbox>
- </template>
- <template v-else>
- <gl-form-checkbox v-model="isResolving" class="js-resolve-checkbox">
- {{ __('Resolve thread') }}
- </gl-form-checkbox>
- </template>
- </label>
- </p>
<div class="gl-display-flex gl-flex-wrap gl-mb-n3">
<gl-button
:disabled="isDisabled"
@@ -451,15 +443,6 @@ export default {
{{ saveButtonTitle }}
</gl-button>
<gl-button
- v-if="discussion.resolvable"
- category="secondary"
- variant="default"
- class="gl-sm-mr-3 gl-xs-mb-3 js-comment-resolve-button"
- @click.prevent="handleUpdate(true)"
- >
- {{ resolveButtonTitle }}
- </gl-button>
- <gl-button
class="note-edit-cancel js-close-discussion-note-form"
category="secondary"
variant="default"
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index 63822a31cd1..814702b724d 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -11,14 +11,6 @@ export default {
return this.note.resolved;
},
resolveButtonTitle() {
- if (this.updatedNoteBody) {
- if (this.discussionResolved) {
- return __('Comment & unresolve thread');
- }
-
- return __('Comment & resolve thread');
- }
-
return this.discussionResolved ? __('Unresolve thread') : __('Resolve thread');
},
},
diff --git a/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue b/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
index 78db2bf15b0..149082d036a 100644
--- a/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/color_picker/color_picker.vue
@@ -110,7 +110,7 @@ export default {
<gl-form-input-group
max-length="7"
type="text"
- class="gl-align-center gl-rounded-0 gl-rounded-top-right-base gl-rounded-bottom-right-base"
+ class="gl-align-center gl-rounded-0 gl-rounded-top-right-base gl-rounded-bottom-right-base gl-max-w-26"
:value="value"
:state="state"
@input="handleColorChange"
diff --git a/app/assets/javascripts/vue_shared/components/listbox_input/init_listbox_inputs.js b/app/assets/javascripts/vue_shared/components/listbox_input/init_listbox_inputs.js
index b447822b1e0..e098103adde 100644
--- a/app/assets/javascripts/vue_shared/components/listbox_input/init_listbox_inputs.js
+++ b/app/assets/javascripts/vue_shared/components/listbox_input/init_listbox_inputs.js
@@ -6,7 +6,7 @@ export const initListboxInputs = () => {
const els = [...document.querySelectorAll('.js-listbox-input')];
els.forEach((el, index) => {
- const { label, description, name, defaultToggleText, value = null } = el.dataset;
+ const { label, description, name, defaultToggleText, value = null, toggleClass } = el.dataset;
const { id } = el;
const items = JSON.parse(el.dataset.items);
@@ -34,6 +34,7 @@ export const initListboxInputs = () => {
block: parseBoolean(el.dataset.block),
fluidWidth: parseBoolean(el.dataset.fluidWidth),
items,
+ toggleClass,
},
attrs: {
id,
diff --git a/app/assets/javascripts/vue_shared/components/listbox_input/listbox_input.vue b/app/assets/javascripts/vue_shared/components/listbox_input/listbox_input.vue
index 09ecad0713a..d20593d104e 100644
--- a/app/assets/javascripts/vue_shared/components/listbox_input/listbox_input.vue
+++ b/app/assets/javascripts/vue_shared/components/listbox_input/listbox_input.vue
@@ -62,6 +62,11 @@ export default {
required: false,
default: GlCollapsibleListbox.props.block.default,
},
+ toggleClass: {
+ type: [Array, String, Object],
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -134,6 +139,7 @@ export default {
<gl-collapsible-listbox
:selected="selected"
:toggle-text="toggleText"
+ :toggle-class="toggleClass"
:items="filteredItems"
:searchable="isSearchable"
:no-results-text="$options.i18n.noResultsText"
diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb
index 59de4fbb698..34b283b87f5 100644
--- a/app/controllers/projects/discussions_controller.rb
+++ b/app/controllers/projects/discussions_controller.rb
@@ -4,8 +4,8 @@ class Projects::DiscussionsController < Projects::ApplicationController
include NotesHelper
include RendersNotes
- before_action :check_merge_requests_available!
- before_action :merge_request
+ before_action :check_noteable_supports_resolvable_notes!
+ before_action :noteable
before_action :discussion, only: [:resolve, :unresolve]
before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve]
@@ -56,13 +56,26 @@ class Projects::DiscussionsController < Projects::ApplicationController
end
# rubocop: disable CodeReuse/ActiveRecord
- def merge_request
- @merge_request ||= MergeRequestsFinder.new(current_user, project_id: @project.id).find_by!(iid: params[:merge_request_id])
+ def noteable
+ @noteable ||= noteable_finder_class.new(current_user, project_id: @project.id).find_by!(iid: params[:noteable_id])
end
# rubocop: enable CodeReuse/ActiveRecord
+ def noteable_finder_class
+ case params[:noteable_type]
+ when 'issues'
+ IssuesFinder
+ when 'merge_requests'
+ MergeRequestsFinder
+ end
+ end
+
+ def check_noteable_supports_resolvable_notes!
+ render_404 unless noteable_finder_class && noteable&.supports_resolvable_notes?
+ end
+
def discussion
- @discussion ||= @merge_request.find_discussion(params[:id]) || render_404
+ @discussion ||= @noteable.find_discussion(params[:id]) || render_404
end
def authorize_resolve_discussion!
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index b30d60652c2..40a91c8ac94 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -17,7 +17,7 @@ module Noteable
# `Noteable` class names that support resolvable notes.
def resolvable_types
- %w(MergeRequest DesignManagement::Design)
+ %w(Issue MergeRequest DesignManagement::Design)
end
# `Noteable` class names that support creating/forwarding individual notes.
@@ -49,6 +49,8 @@ module Noteable
end
def supports_resolvable_notes?
+ return false if is_a?(Issue) && Feature.disabled?(:resolvable_issue_threads, project)
+
self.class.resolvable_types.include?(base_class_name)
end
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index dc4794ed3cd..2d2519dc995 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -191,4 +191,8 @@ class Discussion
def to_global_id(options = {})
GlobalID.new(::Gitlab::GlobalId.build(model_name: Discussion.to_s, id: id))
end
+
+ def noteable_collection_name
+ noteable.class.underscore.pluralize
+ end
end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 8d2baa6ee99..5c23af6e821 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -266,10 +266,15 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
def issues_sentence(project, issues)
# Sorting based on the `#123` or `group/project#123` reference will sort
- # local issues first.
- issues.map do |issue|
+ # local issues numerically first.
+ issue_refs = issues.map do |issue|
issue.to_reference(project)
- end.sort.to_sentence
+ end
+
+ issue_refs.sort_by do |issue_ref|
+ path_section = issue_ref.split('#')
+ [path_section.first, path_section.last.to_i]
+ end.to_sentence
end
def user_can_fork_project?
diff --git a/app/serializers/base_discussion_entity.rb b/app/serializers/base_discussion_entity.rb
index d1aef60a09e..0b006078343 100644
--- a/app/serializers/base_discussion_entity.rb
+++ b/app/serializers/base_discussion_entity.rb
@@ -40,16 +40,16 @@ class BaseDiscussionEntity < Grape::Entity
expose :resolved_at
expose :resolve_path do |discussion|
- resolve_project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion.id)
+ resolve_project_discussion_path(discussion.project, discussion.noteable_collection_name, discussion.noteable, discussion.id)
end
- expose :resolve_with_issue_path do |discussion|
+ expose :resolve_with_issue_path, if: -> (d, _) { d.noteable.is_a?(MergeRequest) } do |discussion|
new_project_issue_path(discussion.project, merge_request_to_resolve_discussions_of: discussion.noteable.iid, discussion_to_resolve: discussion.id) if discussion&.project&.issues_enabled?
end
end
expose :truncated_diff_lines_path, if: -> (d, _) { !d.expanded? && !render_truncated_diff_lines? } do |discussion|
- project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion)
+ project_discussion_path(discussion.project, discussion.noteable_collection_name, discussion.noteable, discussion)
end
private
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index 2155a1b4601..a50d893d244 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -78,10 +78,10 @@ class NoteEntity < API::Entities::Note
end
expose :resolve_path, if: -> (note, _) { note.part_of_discussion? && note.resolvable? } do |note|
- resolve_project_merge_request_discussion_path(note.project, note.noteable, note.discussion_id)
+ resolve_project_discussion_path(discussion.project, discussion.noteable_collection_name, discussion.noteable, discussion.id)
end
- expose :resolve_with_issue_path, if: -> (note, _) { note.part_of_discussion? && note.resolvable? } do |note|
+ expose :resolve_with_issue_path, if: -> (note, _) { note.part_of_discussion? && note.resolvable? && note.noteable.is_a?(MergeRequest) } do |note|
new_project_issue_path(note.project, merge_request_to_resolve_discussions_of: note.noteable.iid, discussion_to_resolve: note.discussion_id)
end
diff --git a/app/serializers/project_note_entity.rb b/app/serializers/project_note_entity.rb
index 3cd34f6af0d..3e004fb5d32 100644
--- a/app/serializers/project_note_entity.rb
+++ b/app/serializers/project_note_entity.rb
@@ -21,14 +21,6 @@ class ProjectNoteEntity < NoteEntity
project_note_path(note.project, note)
end
- expose :resolve_path, if: -> (note, _) { note.part_of_discussion? && note.resolvable? } do |note|
- resolve_project_merge_request_discussion_path(note.project, note.noteable, note.discussion_id)
- end
-
- expose :resolve_with_issue_path, if: -> (note, _) { note.part_of_discussion? && note.resolvable? } do |note|
- new_project_issue_path(note.project, merge_request_to_resolve_discussions_of: note.noteable.iid, discussion_to_resolve: note.discussion_id)
- end
-
expose :delete_attachment_path, if: -> (note, _) { note.attachment? } do |note|
delete_attachment_project_note_path(note.project, note)
end
diff --git a/app/views/discussions/_diff_with_notes.html.haml b/app/views/discussions/_diff_with_notes.html.haml
index a6904495f7c..db122fe82b1 100644
--- a/app/views/discussions/_diff_with_notes.html.haml
+++ b/app/views/discussions/_diff_with_notes.html.haml
@@ -3,7 +3,7 @@
- diff_data = {}
- expanded = discussion.expanded? || local_assigns.fetch(:expanded, nil)
- unless expanded
- - diff_data = { lines_path: project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion) }
+ - diff_data = { lines_path: project_discussion_path(discussion.project, discussion.noteable_collection_name, discussion.noteable, discussion) }
.diff-file.file-holder.js-lazy-load-discussion{ class: diff_file_class, data: diff_data }
.js-file-title.file-title.file-title-flex-parent
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 05a8f64efe1..e7ea139eb71 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -74,14 +74,14 @@
= f.gitlab_ui_radio_component :layout, layout_choices[0][1], layout_choices[0][0], help_text: fixed_help_text
= f.gitlab_ui_radio_component :layout, layout_choices[1][1], layout_choices[1][0], help_text: fluid_help_text
- .js-listbox-input{ data: { label: s_('Preferences|Homepage'), description: s_('Preferences|Choose what content you want to see by default on your homepage.'), name: 'user[dashboard]', items: dashboard_choices.to_json, value: current_user.dashboard, block: true.to_s, fluid_width: true.to_s } }
+ .js-listbox-input{ data: { label: s_('Preferences|Homepage'), description: s_('Preferences|Choose what content you want to see by default on your homepage.'), name: 'user[dashboard]', items: dashboard_choices.to_json, value: current_user.dashboard, block: true.to_s, toggle_class: 'gl-form-input-xl' } }
= render_if_exists 'profiles/preferences/group_overview_selector', f: f # EE-specific
.form-group
= f.label :project_view, class: 'label-bold' do
= s_('Preferences|Project overview content')
- = f.select :project_view, project_view_choices, {}, class: 'gl-form-select custom-select'
+ = f.select :project_view, project_view_choices, {}, class: 'gl-form-select custom-select gl-form-input-xl gl-display-block'
.form-text.text-muted
= s_('Preferences|Choose what content you want to see on a project’s overview page.')
.form-group
@@ -107,7 +107,7 @@
.form-group
= f.label :tab_width, s_('Preferences|Tab width'), class: 'label-bold'
= f.number_field :tab_width,
- class: 'form-control gl-form-input',
+ class: 'form-control gl-form-input gl-max-w-15',
min: Gitlab::TabWidth::MIN,
max: Gitlab::TabWidth::MAX,
required: true
@@ -123,7 +123,8 @@
= _('Customize language and region related settings.')
= succeed '.' do
= link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'localization'), target: '_blank', rel: 'noopener noreferrer'
- .js-listbox-input{ data: { label: _('Language'), description: s_('Preferences|This feature is experimental and translations are not yet complete.'), name: 'user[preferred_language]', items: language_choices.to_json, value: current_user.preferred_language, block: true.to_s, fluid_width: true.to_s } }
+
+ .js-listbox-input{ data: { label: _('Language'), description: s_('Preferences|This feature is experimental and translations are not yet complete.'), name: 'user[preferred_language]', items: language_choices.to_json, value: current_user.preferred_language, block: true.to_s, toggle_class: 'gl-form-input-xl' } }
%p.gl-mt-n5
= link_to help_page_url('development/i18n/translation'), class: 'text-nowrap', target: '_blank', rel: 'noopener noreferrer' do
= _("Help translate GitLab into your language")
@@ -132,7 +133,7 @@
.form-group
= f.label :first_day_of_week, class: 'label-bold' do
= _('First day of the week')
- = f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'gl-form-select custom-select'
+ = f.select :first_day_of_week, first_day_of_week_choices_with_default, {}, class: 'gl-form-select custom-select gl-display-block gl-form-input-xl'
.settings-section.js-preferences-form.js-search-settings-section#time-preferences
.settings-sticky-header